agent-device 0.20.9 → 0.20.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.9.apk → agent-device-android-ime-helper-0.20.10.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.10.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.9.manifest.json → agent-device-android-ime-helper-0.20.10.manifest.json} +4 -4
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.9.apk → agent-device-android-snapshot-helper-0.20.10.apk} +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.10.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.9.manifest.json → agent-device-android-snapshot-helper-0.20.10.manifest.json} +6 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +6 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +4 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+FlatSnapshotFiltering.swift +94 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +22 -23
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +3 -23
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +10 -11
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift +30 -12
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +8 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +133 -63
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +13 -12
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotPresentation.swift +183 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotPresentationTests.swift +0 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +20 -18
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextInputCandidatePolicy.swift +19 -0
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/ai-sdk.d.ts +61 -0
- package/dist/src/ai-sdk.js +1 -0
- package/dist/src/android-adb.d.ts +1 -1
- package/dist/src/app-lifecycle.js +1 -1
- package/dist/src/app-log-reconnect.js +1 -1
- package/dist/src/app-log-runtime.js +3 -3
- package/dist/src/app-resolution.js +2 -2
- package/dist/src/apps.js +5 -5
- package/dist/src/audio-probe.js +1 -1
- package/dist/src/boot-diagnostics.js +2 -2
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +30 -23
- package/dist/src/cli-runner.js +1 -1
- package/dist/src/cli.js +7 -7
- package/dist/src/client-metro.js +1 -1
- package/dist/src/client-types.d.ts +1582 -0
- package/dist/src/command-tools.js +2 -0
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/contracts.d.ts +1 -1
- package/dist/src/contracts.js +1 -1
- package/dist/src/daemon-shutdown-report.js +1 -1
- package/dist/src/daemon.js +1 -1
- package/dist/src/debug-symbols.js +1 -1
- package/dist/src/device-input-state.js +1 -1
- package/dist/src/dispatch.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/generic-settle.js +1 -1
- package/dist/src/generic.js +1 -1
- package/dist/src/helper-package-install.js +1 -1
- package/dist/src/helper.js +1 -1
- package/dist/src/ime-lifecycle.js +1 -1
- package/dist/src/ime-recovery-marker.js +1 -1
- package/dist/src/index.d.ts +2 -1578
- package/dist/src/index.js +1 -1
- package/dist/src/input-actions.js +1 -1
- package/dist/src/input-actions3.js +1 -1
- package/dist/src/install-source2.js +1 -1
- package/dist/src/interaction-common.js +1 -1
- package/dist/src/interaction-runtime.js +1 -1
- package/dist/src/interaction-snapshot.js +1 -1
- package/dist/src/interaction.js +1 -1
- package/dist/src/interaction2.js +1 -1
- package/dist/src/interactor.js +2 -2
- package/dist/src/interactor2.js +1 -1
- package/dist/src/interactors.js +1 -1
- package/dist/src/internal/bin.js +2 -2
- package/dist/src/internal/daemon.js +4 -4
- package/dist/src/internal/png-worker.js +1 -1
- package/dist/src/lease-context.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun.d.ts +10 -2
- package/dist/src/linux.js +1 -1
- package/dist/src/location-coordinates.js +1 -1
- package/dist/src/{screenshot-geometry.js → mobile-snapshot-semantics.js} +1 -1
- package/dist/src/perf.js +1 -1
- package/dist/src/platform-runtime-open-target.js +1 -1
- package/dist/src/platform-runtime-operation-host.js +4 -4
- package/dist/src/platform-runtime.js +1 -1
- package/dist/src/platform-runtime2.js +1 -1
- package/dist/src/png-resize.js +1 -1
- package/dist/src/provider.js +1 -1
- package/dist/src/proxy.js +1 -1
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-runtime.js +1 -1
- package/dist/src/registry.js +27 -27
- package/dist/src/remote-config2.js +1 -1
- package/dist/src/replay.js +2 -2
- 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-sequence.js +1 -1
- package/dist/src/runtime.js +3 -3
- package/dist/src/runtime2.js +4 -4
- package/dist/src/runtime3.js +1 -1
- package/dist/src/runtime4.js +3 -3
- package/dist/src/runtime5.js +1 -1
- package/dist/src/runtime6.js +1 -1
- package/dist/src/runtime7.js +1 -1
- package/dist/src/runtime8.js +1 -1
- package/dist/src/runtime9.js +1 -1
- package/dist/src/screenshot-result.js +4 -4
- package/dist/src/screenshot.js +1 -1
- package/dist/src/script-source-bundle.js +16 -0
- package/dist/src/sdk-android-adb.d.ts +40 -40
- package/dist/src/sdk-android-adb.js +4 -4
- package/dist/src/sdk-batch-runner.js +3 -3
- package/dist/src/sdk-contracts.d.ts +122 -85
- package/dist/src/sdk-contracts.js +2 -2
- package/dist/src/sdk-finders.d.ts +1 -1
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/sdk-selectors.d.ts +89 -77
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selectors.js +1 -1
- package/dist/src/server.js +10 -3
- package/dist/src/session-target-evidence.js +1 -1
- package/dist/src/session2.js +7 -8
- package/dist/src/shared.js +1 -1
- package/dist/src/snapshot-runtime.js +1 -1
- package/dist/src/snapshot-scope.js +1 -0
- package/dist/src/snapshot.js +6 -6
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/snapshot3.js +1 -1
- package/dist/src/src.js +1 -1
- package/dist/src/src2.js +1 -1
- package/dist/src/src3.js +1 -1
- package/dist/src/src4.js +1 -0
- package/dist/src/tool-provider2.js +1 -1
- package/dist/src/tool-provider3.js +1 -0
- package/dist/src/verified-file.js +1 -1
- package/dist/src/web.js +1 -1
- package/package.json +21 -8
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.9.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.9.apk.sha256 +0 -1
- package/dist/src/cancel.js +0 -1
- package/dist/src/prepare-kind.js +0 -15
- package/dist/src/selector-vocabulary.js +0 -1
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
/// Backend-owned snapshot output before it crosses the presentation seam.
|
|
4
|
+
///
|
|
5
|
+
/// The incremental #1797 migration still carries derived fields that later semantic layers move
|
|
6
|
+
/// behind `SnapshotPresentation`. Eligibility is no longer one of those backend-owned decisions.
|
|
7
|
+
struct RawAXNode {
|
|
8
|
+
let index: Int
|
|
9
|
+
let type: String
|
|
10
|
+
let label: String?
|
|
11
|
+
let identifier: String?
|
|
12
|
+
let value: String?
|
|
13
|
+
let rect: SnapshotRect
|
|
14
|
+
let enabled: Bool
|
|
15
|
+
let focused: Bool?
|
|
16
|
+
let selected: Bool?
|
|
17
|
+
let hittable: Bool
|
|
18
|
+
let depth: Int
|
|
19
|
+
let parentIndex: Int?
|
|
20
|
+
let hiddenContentAbove: Bool?
|
|
21
|
+
let hiddenContentBelow: Bool?
|
|
22
|
+
var actions: [String]? = nil
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/// One backend attempt after acquisition and its current backend-specific interpretation.
|
|
26
|
+
///
|
|
27
|
+
/// Step 2 makes this the only input accepted by snapshot presentation. Later #1797 steps move the
|
|
28
|
+
/// interpretation that still precedes this value into `SnapshotPresentation` without changing the
|
|
29
|
+
/// capture-plan seam.
|
|
30
|
+
struct SnapshotAcquisition {
|
|
31
|
+
let nodes: [RawAXNode]
|
|
32
|
+
let truncated: Bool
|
|
33
|
+
let effectiveDepth: Int?
|
|
34
|
+
var customActions: SnapshotCustomActionCoverage? = nil
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/// The only snapshot node shape accepted by response payload assembly.
|
|
38
|
+
///
|
|
39
|
+
/// Its initializer is private so a backend cannot bypass `SnapshotPresentation`. The encoded shape
|
|
40
|
+
/// intentionally remains byte-for-byte compatible with the former `SnapshotNode` wire model.
|
|
41
|
+
struct PresentedNode: Codable {
|
|
42
|
+
let index: Int
|
|
43
|
+
let type: String
|
|
44
|
+
let label: String?
|
|
45
|
+
let identifier: String?
|
|
46
|
+
let value: String?
|
|
47
|
+
let rect: SnapshotRect
|
|
48
|
+
let enabled: Bool
|
|
49
|
+
let focused: Bool?
|
|
50
|
+
let selected: Bool?
|
|
51
|
+
let hittable: Bool
|
|
52
|
+
let depth: Int
|
|
53
|
+
let parentIndex: Int?
|
|
54
|
+
let hiddenContentAbove: Bool?
|
|
55
|
+
let hiddenContentBelow: Bool?
|
|
56
|
+
let actions: [String]?
|
|
57
|
+
|
|
58
|
+
fileprivate init(presenting raw: RawAXNode) {
|
|
59
|
+
self.init(
|
|
60
|
+
presenting: raw,
|
|
61
|
+
index: raw.index,
|
|
62
|
+
depth: raw.depth,
|
|
63
|
+
parentIndex: raw.parentIndex
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
fileprivate init(presenting raw: RawAXNode, index: Int, depth: Int, parentIndex: Int?) {
|
|
68
|
+
self.index = index
|
|
69
|
+
type = raw.type
|
|
70
|
+
label = raw.label
|
|
71
|
+
identifier = raw.identifier
|
|
72
|
+
value = raw.value
|
|
73
|
+
rect = raw.rect
|
|
74
|
+
enabled = raw.enabled
|
|
75
|
+
focused = raw.focused
|
|
76
|
+
selected = raw.selected
|
|
77
|
+
hittable = raw.hittable
|
|
78
|
+
self.depth = depth
|
|
79
|
+
self.parentIndex = parentIndex
|
|
80
|
+
hiddenContentAbove = raw.hiddenContentAbove
|
|
81
|
+
hiddenContentBelow = raw.hiddenContentBelow
|
|
82
|
+
actions = raw.actions
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
enum SnapshotPresentation {
|
|
87
|
+
private static let eligibleInteractiveTypes: Set<String> = [
|
|
88
|
+
"Button",
|
|
89
|
+
"Cell",
|
|
90
|
+
"CheckBox",
|
|
91
|
+
"CollectionView",
|
|
92
|
+
"Link",
|
|
93
|
+
"MenuItem",
|
|
94
|
+
"Picker",
|
|
95
|
+
"SearchField",
|
|
96
|
+
"SecureTextField",
|
|
97
|
+
"SegmentedControl",
|
|
98
|
+
"Slider",
|
|
99
|
+
"ScrollView",
|
|
100
|
+
"Stepper",
|
|
101
|
+
"Switch",
|
|
102
|
+
"TabBar",
|
|
103
|
+
"Table",
|
|
104
|
+
"TextField",
|
|
105
|
+
"TextView",
|
|
106
|
+
"WebView",
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
/// The capture plan's single presentation route for every snapshot backend.
|
|
110
|
+
///
|
|
111
|
+
/// Eligibility is the first intentional step-3 semantic delta: regular presentation keeps a
|
|
112
|
+
/// root carrier plus nodes with an interactive type or non-empty semantic content. Raw snapshots
|
|
113
|
+
/// retain their acquired membership until the dedicated raw-projection migration lands.
|
|
114
|
+
static func present(
|
|
115
|
+
_ acquisition: SnapshotAcquisition,
|
|
116
|
+
options: PresentationOptions
|
|
117
|
+
) -> SnapshotBackendCapture {
|
|
118
|
+
SnapshotBackendCapture(
|
|
119
|
+
payload: DataPayload(
|
|
120
|
+
nodes: presentedNodes(from: acquisition.nodes, options: options),
|
|
121
|
+
truncated: acquisition.truncated
|
|
122
|
+
),
|
|
123
|
+
effectiveDepth: acquisition.effectiveDepth,
|
|
124
|
+
customActions: acquisition.customActions
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/// Explicit carve-out for selector queries and system-modal reads that intentionally return one
|
|
129
|
+
/// already-resolved element instead of traversing a snapshot backend.
|
|
130
|
+
static func singleElementRead(_ node: RawAXNode) -> PresentedNode {
|
|
131
|
+
PresentedNode(presenting: node)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
private static func presentedNodes(
|
|
135
|
+
from rawNodes: [RawAXNode],
|
|
136
|
+
options: PresentationOptions
|
|
137
|
+
) -> [PresentedNode] {
|
|
138
|
+
if options.raw {
|
|
139
|
+
return rawNodes.map(PresentedNode.init(presenting:))
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
var nodes: [PresentedNode] = []
|
|
143
|
+
var nearestPresentedNodeByRawIndex: [Int: (index: Int, depth: Int)] = [:]
|
|
144
|
+
for raw in rawNodes {
|
|
145
|
+
let presentedParent = raw.parentIndex.flatMap {
|
|
146
|
+
nearestPresentedNodeByRawIndex[$0]
|
|
147
|
+
}
|
|
148
|
+
guard isEligibleForRegularPresentation(raw) else {
|
|
149
|
+
if let presentedParent {
|
|
150
|
+
nearestPresentedNodeByRawIndex[raw.index] = presentedParent
|
|
151
|
+
}
|
|
152
|
+
continue
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
let presentedIndex = nodes.count
|
|
156
|
+
let presentedDepth = presentedParent.map { $0.depth + 1 } ?? 0
|
|
157
|
+
nearestPresentedNodeByRawIndex[raw.index] = (presentedIndex, presentedDepth)
|
|
158
|
+
nodes.append(
|
|
159
|
+
PresentedNode(
|
|
160
|
+
presenting: raw,
|
|
161
|
+
index: presentedIndex,
|
|
162
|
+
depth: presentedDepth,
|
|
163
|
+
parentIndex: presentedParent?.index
|
|
164
|
+
)
|
|
165
|
+
)
|
|
166
|
+
}
|
|
167
|
+
return nodes
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
private static func isEligibleForRegularPresentation(_ node: RawAXNode) -> Bool {
|
|
171
|
+
// The top-level carrier owns viewport geometry and must survive even for query-sweep's
|
|
172
|
+
// deliberately unlabeled synthetic Application node.
|
|
173
|
+
if node.parentIndex == nil { return true }
|
|
174
|
+
return eligibleInteractiveTypes.contains(node.type) || hasSemanticContent(node)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private static func hasSemanticContent(_ node: RawAXNode) -> Bool {
|
|
178
|
+
[node.label, node.identifier, node.value].contains { value in
|
|
179
|
+
guard let value else { return false }
|
|
180
|
+
return !value.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
File without changes
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift
CHANGED
|
@@ -25,7 +25,7 @@ extension RunnerTests {
|
|
|
25
25
|
) else {
|
|
26
26
|
return nil
|
|
27
27
|
}
|
|
28
|
-
var nodes: [
|
|
28
|
+
var nodes: [PresentedNode] = [modalNode]
|
|
29
29
|
|
|
30
30
|
for action in actions {
|
|
31
31
|
guard let actionNode = safeMakeSnapshotNode(
|
|
@@ -221,24 +221,26 @@ extension RunnerTests {
|
|
|
221
221
|
depth: Int,
|
|
222
222
|
parentIndex: Int? = nil,
|
|
223
223
|
hittableOverride: Bool? = nil
|
|
224
|
-
) ->
|
|
224
|
+
) -> PresentedNode {
|
|
225
225
|
let label = (labelOverride ?? element.label).trimmingCharacters(in: .whitespacesAndNewlines)
|
|
226
226
|
let identifier = (identifierOverride ?? element.identifier).trimmingCharacters(in: .whitespacesAndNewlines)
|
|
227
|
-
return
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
227
|
+
return SnapshotPresentation.singleElementRead(
|
|
228
|
+
RawAXNode(
|
|
229
|
+
index: index,
|
|
230
|
+
type: type,
|
|
231
|
+
label: label.isEmpty ? nil : label,
|
|
232
|
+
identifier: identifier.isEmpty ? nil : identifier,
|
|
233
|
+
value: nil,
|
|
234
|
+
rect: snapshotRect(from: element.frame),
|
|
235
|
+
enabled: element.isEnabled,
|
|
236
|
+
focused: nil,
|
|
237
|
+
selected: nil,
|
|
238
|
+
hittable: hittableOverride ?? element.isHittable,
|
|
239
|
+
depth: depth,
|
|
240
|
+
parentIndex: parentIndex,
|
|
241
|
+
hiddenContentAbove: nil,
|
|
242
|
+
hiddenContentBelow: nil
|
|
243
|
+
)
|
|
242
244
|
)
|
|
243
245
|
}
|
|
244
246
|
|
|
@@ -251,7 +253,7 @@ extension RunnerTests {
|
|
|
251
253
|
depth: Int,
|
|
252
254
|
parentIndex: Int? = nil,
|
|
253
255
|
hittableOverride: Bool? = nil
|
|
254
|
-
) ->
|
|
256
|
+
) -> PresentedNode? {
|
|
255
257
|
safely("MODAL_NODE") {
|
|
256
258
|
makeSnapshotNode(
|
|
257
259
|
element: element,
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import CoreGraphics
|
|
2
|
+
import XCTest
|
|
3
|
+
|
|
4
|
+
func isCoordinateTextInputCandidate(
|
|
5
|
+
enabled: Bool,
|
|
6
|
+
frame: CGRect,
|
|
7
|
+
point: CGPoint,
|
|
8
|
+
tolerance: CGFloat = 2
|
|
9
|
+
) -> Bool {
|
|
10
|
+
enabled
|
|
11
|
+
&& !frame.isEmpty
|
|
12
|
+
&& point.x >= frame.minX - tolerance
|
|
13
|
+
&& point.x <= frame.maxX + tolerance
|
|
14
|
+
&& point.y >= frame.minY - tolerance
|
|
15
|
+
&& point.y <= frame.maxY + tolerance
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
extension RunnerTests {
|
|
19
|
+
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{n as e}from"./rolldown-runtime.js";import{C as t,E as n,T as r,_ as i,a}from"./sdk-contracts.js";import{h as o,u as s}from"./location-coordinates.js";import{Br as c,Fr as l,Ir as u,Lr as d,Mr as f,Nr as p,Or as m,Pr as h,Rr as g,kr as _,x as ee}from"./sdk-batch-runner.js";import{f as te,o as ne,p as re,s as ie}from"./sdk-device.js";import{At as v,Kt as ae,Qt as oe,en as se,i as ce,kt as le,qt as ue}from"./prepare-kind.js";import{S as de,_ as y,a as fe,ct as b,d as x,dt as pe,f as me,ft as S,i as he,l as ge,m as _e,mt as ve,n as ye,nt as be,u as xe,ut as Se,v as Ce,y as we}from"./screenshot-result.js";import{n as C,t as w}from"./command-catalog.js";import{b as Te,c as Ee,i as De,p as Oe,y as ke}from"./registry.js";import{t as Ae}from"./command-metadata.js";import{A as T,F as je,S as Me,_ as Ne,b as Pe,k as Fe}from"./sdk-android-adb.js";import{r as Ie,t as Le}from"./output-path.js";import{n as E,t as Re}from"./version.js";import{n as ze,t as Be}from"./shell-quote.js";import{t as D}from"./timeouts.js";import{n as Ve,t as He}from"./client-metro.js";import O from"node:path";import{createHash as Ue,randomUUID as We}from"node:crypto";import k from"node:fs";import Ge from"node:os";import{pipeline as A}from"node:stream/promises";import{Transform as Ke,Writable as qe}from"node:stream";import j from"node:net";function Je(e,t){let n=h(e,`bundleId`),r=h(e,`package`);return{app:g(e,`app`),appPath:g(e,`appPath`),platform:d(e,`platform`),appId:n??r,bundleId:n,package:r,identifiers:le({session:t,bundleId:n,packageName:r})}}function Ye(e,t){let n=h(e,`bundleId`),r=h(e,`packageName`),a=n??r??h(e,`appId`),o=h(e,`launchTarget`)??r??n??a;if(!o)throw new i(`COMMAND_FAILED`,`Daemon response is missing "launchTarget".`,{response:e});return{appName:h(e,`appName`),appId:a,bundleId:n,packageName:r,launchTarget:o,installablePath:h(e,`installablePath`),archivePath:h(e,`archivePath`),materializationId:h(e,`materializationId`),materializationExpiresAt:h(e,`materializationExpiresAt`),identifiers:le({session:t,bundleId:n,packageName:r,appId:a})}}function Xe(e){return{released:e.released===!0,materializationId:g(e,`materializationId`),identifiers:{}}}function Ze(e){let{record:t,platform:n,id:r,name:i,target:a}=et(e,`name`),o=$e(t);return{platform:n,target:a,kind:l(t,`kind`),id:r,name:i,booted:typeof t.booted==`boolean`?t.booted:void 0,...ie(n)&&o?{appleOs:o}:{},identifiers:v(n,r,i),...M(n,r)}}function Qe(e){let{record:t,platform:n,id:r,name:i,target:a}=et(e,`name`),o=g(t,`device`),s=$e(t),c={session:i,...v(n,r,o)};return{name:i,createdAt:u(t,`createdAt`),sessionStateDir:h(t,`sessionStateDir`),runnerLogPath:h(t,`runnerLogPath`),device:{platform:n,target:a,id:r,name:o,...s?{appleOs:s}:{},identifiers:c,...M(n,r,{simulatorSetPath:p(t,`ios_simulator_device_set`)})},identifiers:c}}function $e(e){let t=e.appleOs;return ne(t)?t:void 0}function et(e,t){let n=m(e);return{record:n,platform:d(n,`platform`),id:g(n,`id`),name:g(n,t),target:f(n,`target`)}}function M(e,t,n={}){if(e===`ios`)return{ios:{udid:t,...n.simulatorSetPath===void 0?{}:{simulatorSetPath:n.simulatorSetPath}}};if(!re(e))return{};let r=n.serial??t;return e===`android`?{android:{serial:r}}:e===`harmonyos`?{harmonyos:{serial:r}}:{vega:{serial:r}}}function tt(e){if(!_(e))return;let t=e.platform,n=h(e,`metroHost`),r=typeof e.metroPort==`number`?e.metroPort:void 0,i=h(e,`bundleUrl`),a=h(e,`launchUrl`);return{platform:t===`ios`||t===`android`?t:void 0,metroHost:n,metroPort:r,bundleUrl:i,launchUrl:a}}function nt(e){let t=e.platform,n=h(e,`id`),r=h(e,`device`);if(!te(t)||!n||!r)return;let i=f(e,`target`),a=re(t)?h(e,`serial`)??n:void 0;return{platform:t,target:i,id:n,name:r,identifiers:{...v(t,n,r),...a?{serial:a}:{}},...M(t,t===`ios`?h(e,`device_udid`)??n:n,{simulatorSetPath:p(e,`ios_simulator_device_set`),serial:a})}}function rt(e){if(_(e)&&!(typeof e.durationMs!=`number`||typeof e.measuredAt!=`string`||typeof e.method!=`string`))return{durationMs:e.durationMs,measuredAt:e.measuredAt,method:e.method,appTarget:h(e,`appTarget`),appBundleId:h(e,`appBundleId`)}}function it(e){if(!_(e)||typeof e.success!=`boolean`||typeof e.exitCode!=`number`||typeof e.stdout!=`string`||typeof e.stderr!=`string`)return;let t=ot(e.error);return{success:e.success,exitCode:e.exitCode,stdout:e.stdout,stderr:e.stderr,...t?{error:t}:{}}}const at=[`hint`,`diagnosticId`,`logPath`,`supportedOn`];function ot(e){if(!_(e)||typeof e.code!=`string`||typeof e.message!=`string`)return;let t={code:e.code,message:e.message};for(let n of at){let r=e[n];typeof r==`string`&&(t[n]=r)}return _(e.details)&&(t.details=e.details),typeof e.retriable==`boolean`&&(t.retriable=e.retriable),t}function st(e){let t=ot(e.initialSnapshotError);return{...e.snapshot&&typeof e.snapshot==`object`?{snapshot:e.snapshot}:{},...t?{initialSnapshotError:t}:{}}}function ct(e){return Array.isArray(e)?e:[]}function lt(e){let t=ae(e);return c({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,...se(t),sessionIsolation:e.sessionIsolation,installSource:e.installSource,retainMaterializedPaths:e.retainMaterializedPaths,materializedPathRetentionMs:e.materializedPathRetentionMs,materializationId:e.materializationId})}function ut(e){return e??`default`}const dt={...De(),batch:Oe(ft)};function ft(e,t,n){let r=dt[e];if(!r)throw Error(`Missing daemon writer for batch command: ${e}`);let a=Ae(e);if(!a)throw Error(`Missing command metadata for batch command: ${e}`);try{return mt(r,a,a.readInput(t))}catch(t){throw new i(`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,Ae(e),t)}function mt(e,t,n){let r=e(n);return{...r,...t?{metadataFlags:Te(t,r.options)}:{}}}async function ht(e,t){let n=k.statSync(e),r=O.basename(e),i=n.isDirectory(),a=vt(t)??_t(e,n),o=[];try{let t=i?await gt(e,o):e,n=k.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=k.mkdtempSync(O.join(Ge.tmpdir(),`agent-device-upload-${We()}-`));t.push(n);let r=O.join(n,`${O.basename(e)}.tar.gz`);return await Ne(`tar`,[`czf`,r,`-C`,O.dirname(e),O.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)k.rmSync(t,{recursive:!0,force:!0})}async function bt(e){let t=Ue(`sha256`),n=new qe({write(e,n,r){t.update(e),r()}});return await A(k.createReadStream(e),n).catch(e=>{throw new i(`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 Ke({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} (${N(e.totalBytes)}) via ${Tt(e.stage)} upload`;case`resume`:return`Resuming ${e.fileName} at ${N(e.transferredBytes)} of ${N(e.totalBytes)}`;case`progress`:return`Uploaded ${N(e.transferredBytes)} of ${N(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 N(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 P({...e,url:e.url,redirectCount:0,startOffset:0})}function At(e){return e instanceof i&&e.details?.[Ot]===!0}async function P(e){let t=await S(e.url.protocol),n=k.statSync(e.payloadPath).size,r=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:r},t=>{s=!0,ve(t).then(r=>{clearTimeout(l);let s=t.statusCode??500,c=t.headers.location;if(c&&Pt(s)){if(e.redirectCount>=5){o(new i(`COMMAND_FAILED`,`Artifact upload exceeded redirect limit`,{maxRedirects:5,url:e.url.toString()}));return}let t=new URL(c,e.url);P({...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 i(`COMMAND_FAILED`,`Artifact upload resume did not advance`,{offset:u,previousOffset:e.startOffset,url:e.url.toString()}));return}P({...e,startOffset:u}).then(a,o);return}a({statusCode:s,statusMessage:t.statusMessage,body:r})}).catch(o)}),l=setTimeout(()=>{c.destroy(),o(new i(`COMMAND_FAILED`,e.timeoutMessage,{timeoutMs:Dt,...e.timeoutHint?{hint:e.timeoutHint}:{},...jt(e)}))},Dt);c.on(`error`,t=>{s||(clearTimeout(l),o(new i(`COMMAND_FAILED`,e.errorMessage,{...e.errorHint?{hint:e.errorHint}:{},...jt(e)},t)))}),c.on(`close`,()=>clearTimeout(l)),A(k.createReadStream(e.payloadPath,{start:e.startOffset}),xt({stage:e.progress?.stage??`legacy`,fileName:e.progress?.fileName??O.basename(e.payloadPath),startOffset:e.startOffset,totalBytes:n,onProgress:e.progress?.onProgress}),c).catch(e=>{s||(c.destroy(),o(new i(`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=We();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 i?At(e):!0}async function Ut(e){let{normalizedBase:t,token:n,artifact:r}=e,a=new URL(`upload`,t),o={"content-type":r.contentType,"x-artifact-type":r.artifactType,"x-artifact-filename":r.fileName,"x-artifact-hash":r.sha256,"x-artifact-hash-algorithm":`sha256`,"transfer-encoding":`chunked`};Object.assign(o,b(n));let s=await kt({url:a,method:`POST`,headers:o,payloadPath:r.payloadPath,timeoutMessage:`Artifact upload timed out`,timeoutHint:`The upload to the remote daemon exceeded the 5-minute timeout.`,errorMessage:`Failed to upload artifact to remote daemon`,errorHint:`Verify the remote daemon is reachable and supports artifact uploads.`,progress:{stage:`legacy`,fileName:r.fileName,onProgress:e.onProgress}});try{let e=JSON.parse(s.body);if(!e.ok||!e.uploadId)throw new i(`COMMAND_FAILED`,`Upload failed: ${s.body}`);return e.uploadId}catch(e){throw e instanceof i?e:new i(`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,b(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 r=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(r.statusCode<200||r.statusCode>=300)throw new i(`COMMAND_FAILED`,`Direct artifact upload failed`,{statusCode:r.statusCode,statusMessage:r.statusMessage})}async function Jt(e){let t=new URL(`upload/finalize`,e.normalizedBase),n={"content-type":`application/json`};Object.assign(n,b(e.token));let r=await fetch(t,{method:`POST`,headers:n,signal:AbortSignal.timeout(zt),body:JSON.stringify({uploadId:e.uploadId})}).catch(e=>{throw new i(`COMMAND_FAILED`,`Failed to finalize direct artifact upload`,{},e)});if(!r.ok)throw new i(`COMMAND_FAILED`,`Direct artifact upload finalize failed`,{status:r.status,statusText:r.statusText});let a=await r.json().catch(()=>void 0);if(!a?.ok||!a.uploadId)throw new i(`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=O.isAbsolute(e)?e:O.resolve(t??process.cwd(),e);return k.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=O.isAbsolute(i)?i:O.resolve(e.meta?.cwd??process.cwd(),i);if(!k.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:I(`screenshot`,`.png`)}:{field:`path`,localPath:n,positionalIndex:0,flagPath:I(`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:I(`recording`,O.extname(n)||t)}}return null}function rn(e){return Ie(e.flags?.platform)}function an(e){return F(e.positionals?.[1])||F(e.flags?.out)}function on(e,t){return t.flags?.platform===`web`?Le(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=F(i)?i:a;return O.isAbsolute(o)?o:O.resolve(e.meta?.cwd??process.cwd(),o)}function F(e){return typeof e==`string`&&e.trim().length>0}function I(e,t){let n=t.startsWith(`.`)?t:`.${t}`;return O.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 O.resolve(t.meta?.cwd??process.cwd(),r)}async function un(e){let t=new URL(dn(e.baseUrl,e.artifactId)),n=await S(t.protocol);await k.promises.mkdir(O.dirname(e.destinationPath),{recursive:!0}),await new Promise((r,a)=>{let o=!1,s=e.timeoutMs??9e4,c=t=>{if(!o){if(o=!0,clearTimeout(u),t){k.promises.rm(e.destinationPath,{force:!0}).finally(()=>a(t));return}r()}},l=n.request({protocol:t.protocol,host:t.hostname,port:t.port,method:`GET`,path:t.pathname+t.search,headers:{...b(e.token),...Se(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 i(`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 i(`COMMAND_FAILED`,`Remote artifact download was interrupted`,{artifactId:e.artifactId,requestId:e.requestScope?.requestId}))}),A(t,k.createWriteStream(e.destinationPath)).then(()=>c(),e=>c(e instanceof Error?e:Error(String(e))))}),u=setTimeout(()=>{let t=new i(`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 i){c(t);return}c(new i(`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 L(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:z(n.pid)??0,version:R(n.version),codeSignature:R(n.codeSignature),processStartTime:R(n.processStartTime)}:null}function hn(e){return typeof e.token==`string`&&e.token.length>0?e.token:null}function gn(e){let t=z(e.port),n=z(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 R(e){return typeof e==`string`?e:void 0}function z(e){return Number.isInteger(e)&&Number(e)>0?Number(e):void 0}function B(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 V(e){wn(e)}function H(e){wn(e)}function vn(e){let t=W(e);if(!t.hasLock||t.hasInfo)return;let n=B(e.lockPath);if(!n){H(e.lockPath);return}x(n.pid,n.processStartTime)||H(e.lockPath)}async function U(e,t,n={}){let r=n.stopLiveProcesses??!0,i={reason:t,removedInfo:!1,removedLock:!1,stoppedInfoProcess:!1,stoppedLockProcess:!1};try{let t=k.existsSync(e.infoPath),n=L(e.infoPath);if(n){let t=x(n.pid,n.processStartTime);t&&!r?i.retainedInfoProcess=!0:(t&&(await G(n),i.stoppedInfoProcess=!0),V(e.infoPath),i.removedInfo=!0)}else t&&(V(e.infoPath),i.removedInfo=!0);let a=k.existsSync(e.lockPath),o=B(e.lockPath);if(o){let t=x(o.pid,o.processStartTime);t&&!r?i.retainedLockProcess=!0:(t&&(await me(o.pid,{termTimeoutMs:pn,killTimeoutMs:mn,expectedStartTime:o.processStartTime}),i.stoppedLockProcess=!0),H(e.lockPath),i.removedLock=!0)}else a&&(H(e.lockPath),i.removedLock=!0)}catch(e){i.error=e instanceof Error?e.message:String(e)}return T({level:i.error?`warn`:`info`,phase:`daemon_startup_metadata_cleanup`,data:i}),i}function W(e){return{hasInfo:k.existsSync(e.infoPath),hasLock:k.existsSync(e.lockPath)}}async function yn(e){let t=W(e);if(!t.hasLock||t.hasInfo)return!1;let n=B(e.lockPath);return!n||!x(n.pid,n.processStartTime)?(H(e.lockPath),!0):!1}async function G(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(!k.existsSync(e))return null;try{return JSON.parse(k.readFileSync(e,`utf8`))}catch{return null}}function wn(e){try{k.existsSync(e)&&k.unlinkSync(e)}catch{}}function Tn(e,t){if(t.onProgress){t.onProgress(e);return}e.type===`command`&&(t.req.command===`doctor`&&ce(),process.stderr.write(`${e.message}\n`))}function K(e,t,n){return new i(`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(K(e.req,n,r))}if(he(r))try{return Tn(r.event,{req:e.req,onProgress:e.onProgress}),!1}catch(e){return t(e)}return fe(r)?(e.onResponse(r.response),!0):e.responseFormat===`socket-legacy`?(e.onResponse(r),!0):t(K(e.req,n,Error(`Missing daemon progress response envelope`)))}}}function Dn(e,t){return ge(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=xe(s,e);s=t.buffer;for(let e of t.lines)if(c.handleLine(e))return})}function kn(e,t){let{req:n,handleResponseBody:r,reject:a,clearTimeout:o}=t,s=``,c=!1,l=En({req:n,onProgress:t.onProgress,responseFormat:`ndjson-envelope`,onResponse(e){c=!0,o(),r(JSON.stringify(e))},onError(e){c=!0,o(),a(e)}});e.setEncoding(`utf8`),e.on(`data`,e=>{if(c)return;let t=xe(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(K(n,e)))}),e.on(`error`,e=>{c||(c=!0,o(),a(new i(`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:r,resolve:a,reject:o}=t;try{let t=jn(e);if(t.error){o(Mn(t.error,r.meta?.requestId));return}if(!t.result||typeof t.result!=`object`){o(new i(`COMMAND_FAILED`,`Invalid daemon RPC response`,{requestId:r.meta?.requestId}));return}Nn(n,r,t.result,a,o)}catch(t){o(new i(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:r.meta?.requestId,line:e},t instanceof Error?t:void 0))}}function jn(e){return JSON.parse(e)}function Mn(e,t){let r=e.data??{};return new i(n(r.code==null?void 0:String(r.code),`COMMAND_FAILED`),String(r.message??e.message??`Daemon RPC request failed`),{...typeof r.details==`object`&&r.details?r.details:{},hint:typeof r.hint==`string`?r.hint:void 0,diagnosticId:typeof r.diagnosticId==`string`?r.diagnosticId:void 0,logPath:typeof r.logPath==`string`?r.logPath:void 0,retriable:typeof r.retriable==`boolean`?r.retriable:void 0,supportedOn:typeof r.supportedOn==`string`?r.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??Fe();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 oe(ue(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`],zn=new Set([`apple`,`ios`,`macos`]);function Bn(e){return e!==void 0&&zn.has(e)}function Vn(e){let t=ee(e.command);if(t.envelopeMs===`unbounded`)return;let n={...t,envelopeMs:t.envelopeMs};return Hn(n,e.positionals??[])??Un(n,e.flags)??n.envelopeMs}function Hn(e,t){if(e.budget.source!==`positional-parser`)return;let n=e.budget.parser(t);return n===null?void 0:Gn(e,n)}function Un(e,t){if(e.budget.source===`flag`)return e.budget.envelope===`widen`?Wn(e,e.budget,t):typeof t?.timeoutMs==`number`?t.timeoutMs:e.envelopeMs}function Wn(e,t,n){if(n?.settle!==!0)return e.envelopeMs;let r=typeof n.timeoutMs==`number`?n.timeoutMs:t.defaultBudgetMs;return typeof r==`number`?Kn(e,r):e.envelopeMs}function Gn(e,t){return Math.max(e.envelopeMs,t+Qn)}function Kn(e,t){return Math.max(e.envelopeMs,e.envelopeMs+t+Qn)}function qn(e,t,n,r,a,o,s){let c=a?{terminated:0}:Xn(),l=!a&&Jn(r),u=l?Zn(e,t):{forcedKill:!1},d=Bn(s)||c.terminated>0;return T({level:`error`,phase:`daemon_request_timeout`,data:{timeoutMs:o,requestId:n,command:r,timedOutRunnerPidsTerminated:c.terminated,timedOutRunnerCleanupError:c.error,daemonPidReset:l?e.pid:void 0,daemonPidForceKilled:l?u.forcedKill:void 0,daemonPreservedAfterTimeout:!a&&!l,daemonBaseUrl:e.baseUrl}}),new i(`COMMAND_FAILED`,`Daemon request timed out`,{timeoutMs:o,requestId:n,hint:Yn({remote:a,resetDaemon:l,command:r,appleCleanupEvidence:d})})}function Jn(e){return ee(e).onTimeout===`reset-daemon`}function Yn(e){let{remote:t,resetDaemon:n,command:r,appleCleanupEvidence:i}=e;if(t)return`Retry with --debug and verify the remote daemon URL, auth token, and remote host logs.`;if(!n){let e=i&&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${i?` and Apple runner work was aborted when detected`:``}; the daemon was kept alive so the session can still be closed or inspected.${e}`}return i?`Retry with --debug and check daemon diagnostics logs. Timed-out Apple runner xcodebuild processes were terminated when detected.`:`Retry with --debug and check daemon diagnostics logs. The daemon was reset after the timeout.`}function Xn(){let e=0;try{for(let t of Rn)Me(`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 Zn(e,t){let n=!1;try{x(e.pid,e.processStartTime)&&(process.kill(e.pid,`SIGKILL`),n=!0)}catch{G(e)}finally{V(t.infoPath),H(t.lockPath)}return{forcedKill:n}}const Qn=3e4,$n=`Daemon HTTP endpoint is unavailable`,er=`Daemon socket endpoint is unavailable`;async function tr(e,t){let n=ur(e,t);if(await nr(e,n))return!0;let r=dr(e,t,n);return r?await nr(e,r):!1}async function nr(e,t){return t===`http`?await ir(e):await rr(e.port)}function rr(e){return e?new Promise(t=>{let n=!1,r=j.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 ir(e){return or(e).then(e=>e.reachable)}async function ar(e){let t=await or(e);if(!e.baseUrl||!t.reachable)return t;if(typeof t.rpcProtocolVersion==`number`&&t.rpcProtocolVersion!==2)throw new i(`COMMAND_FAILED`,`Remote daemon RPC protocol is incompatible`,{daemonBaseUrl:e.baseUrl,clientVersion:E(),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}async function or(e){let t=e.baseUrl?pe(e.baseUrl,`health`):e.httpPort?`http://127.0.0.1:${e.httpPort}/health`:null;if(!t)return{reachable:!1};let n=new URL(t),r=await S(n.protocol),i=e.baseUrl?3e3:500;return await new Promise(t=>{let a=e.baseUrl?b(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,...sr(n)})})});o.on(`timeout`,()=>{o.destroy(),t({reachable:!1})}),o.on(`error`,()=>{t({reachable:!1})}),o.end()})}function sr(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 cr(e,t,n,r,i,a={}){let o=ur(e,n);try{return await lr(e,t,r,i,o,a)}catch(s){let c=dr(e,n,o);if(!c||!fr(s,o))throw s;return await lr(e,t,r,i,c,a)}}async function lr(e,t,n,r,i,a){return i===`http`?await gr(e,t,n,r,a):await hr(e,t,n,r,a)}function ur(e,t){if(e.baseUrl){if(t===`socket`)throw new i(`COMMAND_FAILED`,`Remote daemon endpoint only supports HTTP transport`,{daemonBaseUrl:e.baseUrl});return`http`}if(t===`http`||t===`socket`)return pr(e,t);let n=(e.transport===`socket`||e.transport===`dual`?[`socket`,`http`]:[`http`,`socket`]).find(t=>q(e,t));if(n)return n;throw new i(`COMMAND_FAILED`,`Daemon metadata has no reachable transport`)}function q(e,t){return t===`http`?!!e.httpPort:!!e.port}function dr(e,t,n){if(t!==`auto`||e.baseUrl)return null;let r=n===`socket`?`http`:`socket`;return q(e,r)?r:null}function fr(e,t){return t===`socket`&&e instanceof i&&e.code===`COMMAND_FAILED`&&e.message===`Failed to communicate with daemon`&&e.details?.daemonSocketRequestWritten===!1}function pr(e,t){if(q(e,t))return t;throw new i(`COMMAND_FAILED`,t===`http`?$n:er)}function mr(e,t,n,r={}){return T({level:`error`,phase:`daemon_request_socket_error`,data:{requestId:t,message:e instanceof Error?e.message:String(e)}}),new i(`COMMAND_FAILED`,`Failed to communicate with daemon`,{...r,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 hr(e,t,n,r,a){let o=e.port;if(!o)throw new i(`COMMAND_FAILED`,er);return new Promise((i,s)=>{let c=!1,l=j.createConnection({host:`127.0.0.1`,port:o},()=>{c=!0,l.write(`${JSON.stringify(t)}\n`)}),u=!1,d=typeof r==`number`?setTimeout(()=>{u=!0,l.destroy(),s(qn(e,n,t.meta?.requestId,t.command,!1,r,t.flags?.platform))},r):void 0;On(l,{req:t,onProgress:a.onProgress,isSettled:()=>u,clearTimeout:()=>{d&&clearTimeout(d)},resolve:e=>{u=!0,i(e)},reject:e=>{u=!0,s(e)}}),l.on(`error`,e=>{u||(u=!0,d&&clearTimeout(d),s(mr(e,t.meta?.requestId,!1,{daemonSocketRequestWritten:c})))})})}async function gr(e,t,n,r,a){let o=e.baseUrl?new URL(pe(e.baseUrl,`rpc`)):e.httpPort?new URL(`http://127.0.0.1:${e.httpPort}/rpc`):null;if(!o)throw new i(`COMMAND_FAILED`,$n);let s=JSON.stringify(Pn(t,{includeTokenParam:!e.baseUrl})),c={"content-type":`application/json`,"content-length":Buffer.byteLength(s)};e.baseUrl&&Object.assign(c,b(e.token));let l=await S(o.protocol);return await new Promise((u,d)=>{let f=l.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:d,clearTimeout:()=>{m&&clearTimeout(m)},handleResponseBody:n=>An(n,{info:e,req:t,resolve:u,reject:d})});return}ve(n).then(n=>{m&&clearTimeout(m),An(n,{info:e,req:t,resolve:u,reject:d})}).catch(e=>{m&&clearTimeout(m),d(new i(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:t.meta?.requestId},e instanceof Error?e:void 0))})}),p=bn(e),m=typeof r==`number`?setTimeout(()=>{f.destroy(),d(qn(e,n,t.meta?.requestId,t.command,p,r,t.flags?.platform))},r):void 0;f.on(`error`,e=>{m&&clearTimeout(m),d(mr(e,t.meta?.requestId,p))}),f.write(s),f.end()})}const J=15e3,Y=new j.BlockList;Y.addSubnet(`127.0.0.0`,8,`ipv4`),Y.addAddress(`::1`,`ipv6`),Y.addSubnet(`::ffff:127.0.0.0`,104,`ipv6`);function _r(e,t){let n=vr(e),r=yr(e,t),i=br(e,r.remoteBaseUrl),a=xr(e,n,r.rawBaseUrl);return{paths:y(a?Sr():n),transportPreference:i.preference,serverMode:i.serverMode,ownedStateDir:a,remoteBaseUrl:r.remoteBaseUrl,remoteAuthToken:r.authToken}}function vr(e){return e.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR}function yr(e,t){let n=e.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL,r=Gr(n),i=t??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN;return Kr(r,i),{rawBaseUrl:n,remoteBaseUrl:r,authToken:i}}function br(e,t){let n=e.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,r=we(n);if(t&&r===`socket`)throw new i(`INVALID_ARGS`,`Remote daemon base URL only supports HTTP transport. Remove --daemon-transport socket.`,{daemonBaseUrl:t});return{preference:r,serverMode:Ce(e.flags?.daemonServerMode??process.env.AGENT_DEVICE_DAEMON_SERVER_MODE??(n===`dual`?`dual`:void 0))}}function xr(e,t,n){return Ir(e.command)&&!t&&!n}function Sr(){return k.mkdtempSync(O.join(Ge.tmpdir(),`agent-device-replay-daemon-`))}async function Cr(e){if(e.remoteBaseUrl)return await wr(e);let t=await Tr(e);return t?{info:t,startedByClient:!1}:(vn(e.paths),await jr(e))}async function wr(e){let t={transport:`http`,token:e.remoteAuthToken??``,pid:0,baseUrl:e.remoteBaseUrl};if((await ar(t)).reachable)return{info:t,startedByClient:!1};throw new i(`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 Tr(e){let t=L(e.paths.infoPath);if(!t)return null;let n=await Er(t,e.transportPreference);return Or(t,n)?t:(kr(t,n,e.paths.baseDir),await G(t),V(e.paths.infoPath),null)}async function Er(e,t){try{return await tr(e,t)}catch(e){if(Dr(e))return!1;throw e}}function Dr(e){return e instanceof i&&e.code===`COMMAND_FAILED`&&(e.message===`Daemon HTTP endpoint is unavailable`||e.message===`Daemon socket endpoint is unavailable`)}function Or(e,t){return e.version===E()&&e.codeSignature===Hr()&&t}function kr(e,t,n){try{let r=e.version?`pid ${e.pid}, v${e.version}`:`pid ${e.pid}`,i=Ar(e,t);process.stderr.write(`Replacing daemon (${r}) in ${n}: ${i}\n`)}catch{}}function Ar(e,t){return e.version===E()?e.codeSignature===Hr()?t?`not reusable`:`unreachable`:`code-signature mismatch`:`version mismatch (client v${E()})`}async function jr(e){let t=0,n=[],r,a;for(let i=1;i<=2;i+=1){let o;try{o=Br(e),a={pid:o.pid}}catch(t){if(r=t instanceof Error?t.message:String(t),n.push(await U(e.paths,`start_error`)),i<2){await D(150);continue}break}let s=await zr(J,e,o);if(s.kind===`ready`)return{info:s.info,startedByClient:!0};if(s.kind===`early_exit`){if(a=s.exit,r=Ur(s.exit),n.push(await U(e.paths,`start_error`)),i<2){await D(150);continue}break}if(await yn(e.paths)){t+=1;continue}let c=W(e.paths),l=i<2,u=await U(e.paths,`startup_timeout`,{stopLiveProcesses:!1});if(n.push(u),u.retainedInfoProcess||u.retainedLockProcess){let t=await zr(J,e,o);if(t.kind===`ready`)return{info:t.info,startedByClient:!0};t.kind===`early_exit`&&(a=t.exit,r=Ur(t.exit));break}if(!l)break;!c.hasInfo&&!c.hasLock&&await D(150)}let o=W(e.paths),s=Wr(e.paths.logPath);throw new i(`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:J,startupAttempts:2,lockRecoveryCount:t,cleanupResults:n,startError:r,daemonProcess:a,...s?{daemonLogTail:s}:{},metadataState:o,hint:xn(o,e.paths)})}async function Mr(e,t,n,r){if(!Ir(e.command)||!t.startedByClient&&!n.ownedStateDir||bn(t.info)||Pr(r)||Lr(e,r))return r;let i={pid:t.info.pid,removedInfo:!1,removedLock:!1,removedStateDir:!1,error:void 0},a=r;try{await G(t.info)}catch(e){i.error=e instanceof Error?e.message:String(e)}finally{let e=k.existsSync(n.paths.infoPath);V(n.paths.infoPath),i.removedInfo=e&&!k.existsSync(n.paths.infoPath);let t=k.existsSync(n.paths.lockPath);if(H(n.paths.lockPath),i.removedLock=t&&!k.existsSync(n.paths.lockPath),n.ownedStateDir){let e=de(n.paths.sessionsDir);e?a=Nr(r,e):(k.rmSync(n.paths.baseDir,{recursive:!0,force:!0}),i.removedStateDir=!k.existsSync(n.paths.baseDir))}}return T({level:i.error?`warn`:`info`,phase:`daemon_replay_cleanup`,data:i}),a}function Nr(e,n){if(e&&!e.ok)return e;let{sessionName:r,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 i(`REPAIR_COMMIT_FAILED`,`The repair transaction for session "${r}" completed, but committing its healed script failed at teardown: ${a.commitFailure.message}. ${o}.`))}}function Pr(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 Fr(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 Ir(e){return e===C.replay||e===C.test}function Lr(e,t){return e.command!==C.replay||!t||!t.ok?!1:t.data?.sessionActive===!0}function Rr(e,t){let n=e.data??{},r=typeof n.session==`string`?n.session:void 0,i=[...t?[`--state-dir ${ze(t)}`]:[],...r?[`--session ${ze(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 zr(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=L(t.paths.infoPath);if(e&&await tr(e,t.transportPreference))return{kind:`ready`,info:e};if(i)return{kind:`early_exit`,exit:i};await D(100)}return{kind:`timeout`}}function Br(e){let t=Vr(),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};k.mkdirSync(e.paths.baseDir,{recursive:!0});let i=k.openSync(e.paths.logPath,`a`),a=k.openSync(e.paths.logPath,`a`);try{return Pe(process.execPath,n,{env:r,stdio:[`ignore`,i,a]})}finally{k.closeSync(i),k.closeSync(a)}}function Vr(){let e=Re(),t=[O.join(e,`dist`,`src`,`internal`,`daemon.js`),O.join(e,`dist`,`src`,`daemon.js`)],n=t[0];if(n===void 0)throw new i(`COMMAND_FAILED`,`Daemon dist path list is empty`);let r=t.find(e=>k.existsSync(e))??n,a=O.join(e,`src`,`daemon.ts`),o=t.some(e=>k.existsSync(e)),s=k.existsSync(a);if(!o&&!s)throw new i(`COMMAND_FAILED`,`Daemon entry not found`,{distPaths:t,srcPath:a});return{root:e,distPath:r,distPaths:t,srcPath:a,useSrc:(process.execArgv.includes(`--experimental-strip-types`)||!o)&&s}}function Hr(){let e=Vr();return _e(e.useSrc?e.srcPath:e.distPath,e.root)}function Ur(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 Wr(e){try{if(!k.existsSync(e))return;let t=k.statSync(e);if(t.size<=0)return;let n=Math.min(t.size,64e3),r=k.openSync(e,`r`);try{let e=Buffer.alloc(n);k.readSync(r,e,0,n,t.size-n);let i=e.toString(`utf8`).trim();return i.length>0?i:void 0}finally{k.closeSync(r)}}catch{return}}function Gr(e){if(!e)return;let t;try{t=new URL(e)}catch(t){throw new i(`INVALID_ARGS`,`Invalid daemon base URL`,{daemonBaseUrl:e},t instanceof Error?t:void 0)}if(t.protocol!==`http:`&&t.protocol!==`https:`)throw new i(`INVALID_ARGS`,`Daemon base URL must use http or https`,{daemonBaseUrl:e});return t.toString().replace(/\/+$/,``)}function Kr(e,t){if(!e)return;let n=new URL(e).hostname;if(!qr(n)&&!(typeof t==`string`&&t.trim().length>0))throw new i(`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 qr(e){let t=e.trim().toLowerCase().replace(/^\[(.*)\]$/,`$1`);return t===`localhost`?!0:j.isIPv4(t)?Y.check(t,`ipv4`):j.isIPv6(t)?Y.check(t,`ipv6`):!1}async function Jr(e,t={}){let n=e.meta?.requestId??Fe(),r=!!(e.meta?.debug||e.flags?.verbose),i=e.flags,{daemonAuthToken:a,...o}=i??{},s=i?{...e,flags:o}:e,c=_r(s,t.authToken??a),l=Vn(s),u=await je(`daemon_startup`,async()=>await Cr(c),{requestId:n,session:e.session}),d=u.info,f=await Yt(s,d);ni(s.command);let p=Yr(s,f,d.token,n,r);return T({level:`info`,phase:`daemon_request_prepare`,data:{requestId:n,command:s.command,session:s.session}}),await $r(s,u,c,async()=>ti(ei(await je(`daemon_request`,async()=>await cr(d,p,c.transportPreference,c.paths,l,t.onProgress?{onProgress:t.onProgress}:void 0),{requestId:n,command:e.command}),c),s,c))}function Yr(e,t,n,r,i){return{...e,positionals:t.positionals,flags:t.flags,token:n,meta:Xr(e,t,r,i)}}function Xr(e,t,n,r){let i=e.meta??{};return{...i,requestId:n,debug:r,...Zr(i,e.flags),...Qr(t)}}function Zr(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 Qr(e){return{...e.uploadedArtifactId?{uploadedArtifactId:e.uploadedArtifactId}:{},...e.clientArtifactPaths?{clientArtifactPaths:e.clientArtifactPaths}:{},...e.installSource?{installSource:e.installSource}:{}}}async function $r(e,t,n,r){let a,o=!1,s;try{a=await r()}catch(e){o=!0,s=e}let c=await Mr(e,t,n,a);if(o)throw s;if(!c)throw new i(`COMMAND_FAILED`,`Daemon request produced no response after cleanup`);return c}function ei(e,t){return e.ok||!t.ownedStateDir||!Pr(e)?e:Fr(e,t.paths.baseDir)}function ti(e,t,n){return!e.ok||!Lr(t,e)?e:Rr(e,n.ownedStateDir?n.paths.baseDir:void 0)}function ni(e){!ri(e)||process.stderr.isTTY!==!0||process.env.CI||process.stderr.write(e===C.reinstall?`Reinstalling...
|
|
1
|
+
import{n as e}from"./rolldown-runtime.js";import{A as t,D as n,E as r,_ as i,a,k as o}from"./sdk-contracts.js";import{h as s,u as c}from"./location-coordinates.js";import{Br as l,C as u,Gr as d,Hr as f,Ir as p,Jr as m,Kr as h,Lr as g,Ur as ee,Vr as te,Wr as ne,Xt as re}from"./sdk-batch-runner.js";import{f as ie,o as ae,p as oe,s as se}from"./sdk-device.js";import{An as ce,Mn as le,Tn as ue,cn as _,sn as de,u as fe,wn as pe}from"./script-source-bundle.js";import{C as me,S as he,_ as v,_t as ge,a as _e,at as ve,d as y,dt as b,f as ye,ht as x,i as be,l as xe,m as Se,mt as S,n as Ce,pt as we,u as Te,v as Ee,y as De}from"./screenshot-result.js";import{n as C,t as w}from"./command-catalog.js";import{b as Oe,c as ke,i as Ae,p as je,y as Me}from"./registry.js";import{t as Ne}from"./command-metadata.js";import{A as T,F as Pe,S as Fe,_ as Ie,b as Le,k as Re}from"./sdk-android-adb.js";import{r as ze,t as Be}from"./output-path.js";import{n as E,t as Ve}from"./version.js";import{n as He,t as Ue}from"./shell-quote.js";import{t as D}from"./timeouts.js";import{n as We,t as Ge}from"./client-metro.js";import O from"node:path";import{createHash as Ke,randomUUID as qe}from"node:crypto";import k from"node:fs";import Je from"node:os";import{pipeline as A}from"node:stream/promises";import{Transform as Ye,Writable as Xe}from"node:stream";import j from"node:net";function Ze(e,t){let n=f(e,`bundleId`),r=f(e,`package`);return{app:h(e,`app`),appPath:h(e,`appPath`),platform:d(e,`platform`),appId:n??r,bundleId:n,package:r,identifiers:de({session:t,bundleId:n,packageName:r})}}function Qe(e,t){let n=f(e,`bundleId`),r=f(e,`packageName`),a=n??r??f(e,`appId`),o=f(e,`launchTarget`)??r??n??a;if(!o)throw new i(`COMMAND_FAILED`,`Daemon response is missing "launchTarget".`,{response:e});return{appName:f(e,`appName`),appId:a,bundleId:n,packageName:r,launchTarget:o,installablePath:f(e,`installablePath`),archivePath:f(e,`archivePath`),materializationId:f(e,`materializationId`),materializationExpiresAt:f(e,`materializationExpiresAt`),identifiers:de({session:t,bundleId:n,packageName:r,appId:a})}}function $e(e){return{released:e.released===!0,materializationId:h(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:ee(t,`kind`),id:r,name:i,booted:typeof t.booted==`boolean`?t.booted:void 0,...se(n)&&o?{appleOs:o}:{},identifiers:_(n,r,i),...M(n,r)}}function tt(e){let{record:t,platform:n,id:r,name:i,target:a}=rt(e,`name`),o=h(t,`device`),s=nt(t),c={session:i,..._(n,r,o)};return{name:i,createdAt:ne(t,`createdAt`),sessionStateDir:f(t,`sessionStateDir`),runnerLogPath:f(t,`runnerLogPath`),device:{platform:n,target:a,id:r,name:o,...s?{appleOs:s}:{},identifiers:c,...M(n,r,{simulatorSetPath:te(t,`ios_simulator_device_set`)})},identifiers:c}}function nt(e){let t=e.appleOs;return ae(t)?t:void 0}function rt(e,t){let n=p(e);return{record:n,platform:d(n,`platform`),id:h(n,`id`),name:h(n,t),target:l(n,`target`)}}function M(e,t,n={}){if(e===`ios`)return{ios:{udid:t,...n.simulatorSetPath===void 0?{}:{simulatorSetPath:n.simulatorSetPath}}};if(!oe(e))return{};let r=n.serial??t;return e===`android`?{android:{serial:r}}:e===`harmonyos`?{harmonyos:{serial:r}}:{vega:{serial:r}}}function it(e){if(!g(e))return;let t=e.platform,n=f(e,`metroHost`),r=typeof e.metroPort==`number`?e.metroPort:void 0,i=f(e,`bundleUrl`),a=f(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=f(e,`id`),r=f(e,`device`);if(!ie(t)||!n||!r)return;let i=l(e,`target`),a=oe(t)?f(e,`serial`)??n:void 0;return{platform:t,target:i,id:n,name:r,identifiers:{..._(t,n,r),...a?{serial:a}:{}},...M(t,t===`ios`?f(e,`device_udid`)??n:n,{simulatorSetPath:te(e,`ios_simulator_device_set`),serial:a})}}function ot(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:f(e,`appTarget`),appBundleId:f(e,`appBundleId`)}}function st(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}:{}}}const ct=[`hint`,`diagnosticId`,`logPath`,`supportedOn`];function lt(e){if(!g(e)||typeof e.code!=`string`||typeof e.message!=`string`)return;let t={code:e.code,message:e.message};for(let n of ct){let r=e[n];typeof r==`string`&&(t[n]=r)}return g(e.details)&&(t.details=e.details),typeof e.retriable==`boolean`&&(t.retriable=e.retriable),t}function ut(e){let t=lt(e.initialSnapshotError);return{...e.snapshot&&typeof e.snapshot==`object`?{snapshot:e.snapshot}:{},...t?{initialSnapshotError:t}:{}}}function dt(e){return Array.isArray(e)?e:[]}function ft(e){let t=pe(e);return m({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 N(e){return e??`default`}const pt={...Ae(),batch:je(mt)};async function mt(e,t,n){let r=pt[e];if(!r)throw Error(`Missing daemon writer for batch command: ${e}`);let a=Ne(e);if(!a)throw Error(`Missing command metadata for batch command: ${e}`);try{return await gt(r,a,a.readInput(t))}catch(t){throw new i(`INVALID_ARGS`,`Batch step ${n} ${e} input is invalid: ${t instanceof Error?t.message:String(t)}`,void 0,t)}}async function ht(e,t){let n=pt[e];if(!n)throw Error(`Missing daemon writer for command: ${e}`);return await gt(n,Ne(e),t)}async function gt(e,t,n){let r=await e(n);return{...r,...t?{metadataFlags:Oe(t,r.options)}:{}}}async function _t(e,t){let n=k.statSync(e),r=O.basename(e),i=n.isDirectory(),a=bt(t)??yt(e,n),o=[];try{let t=i?await vt(e,o):e,n=k.statSync(t);return{payloadPath:t,fileName:r,artifactType:i?`app-bundle`:`file`,platform:a,contentType:i?`application/gzip`:`application/octet-stream`,sha256:await St(t),sizeBytes:n.size,cleanup:()=>xt(o)}}catch(e){throw xt(o),e}}async function vt(e,t){let n=k.mkdtempSync(O.join(Je.tmpdir(),`agent-device-upload-${qe()}-`));t.push(n);let r=O.join(n,`${O.basename(e)}.tar.gz`);return await Ie(`tar`,[`czf`,r,`-C`,O.dirname(e),O.basename(e)],{env:{...process.env,COPYFILE_DISABLE:`1`}}),r}function yt(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 bt(e){return e===`ios`||e===`android`?e:void 0}function xt(e){for(let t of e)k.rmSync(t,{recursive:!0,force:!0})}async function St(e){let t=Ke(`sha256`),n=new Xe({write(e,n,r){t.update(e),r()}});return await A(k.createReadStream(e),n).catch(e=>{throw new i(`COMMAND_FAILED`,`Failed to read local artifact`,{},e instanceof Error?e:void 0)}),t.digest(`hex`)}function Ct(e){let{stage:t,fileName:n,startOffset:r,totalBytes:i,onProgress:a}=e,o=r,s=Et(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 wt(){if(!(process.stderr.isTTY!==!0||process.env.CI))return e=>{process.stderr.write(`${Tt(e)}\n`)}}function Tt(e){switch(e.type){case`start`:return`Uploading ${e.fileName} (${P(e.totalBytes)}) via ${Dt(e.stage)} upload`;case`resume`:return`Resuming ${e.fileName} at ${P(e.transferredBytes)} of ${P(e.totalBytes)}`;case`progress`:return`Uploaded ${P(e.transferredBytes)} of ${P(e.totalBytes)} (${Ot(e.transferredBytes,e.totalBytes)})`;case`fallback`:return`Direct upload did not complete; retrying ${e.fileName} with ${Dt(e.to)} upload`}}function Et(e){return Math.max(8388608,Math.ceil(e*.05))}function Dt(e){return e===`direct`?`direct`:`legacy`}function Ot(e,t){return t<=0?`100%`:`${Math.min(100,Math.floor(e/t*100))}%`}function P(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 kt=300*1e3,At=`uploadStreamRetryable`;async function jt(e){return await F({...e,url:e.url,redirectCount:0,startOffset:0})}function Mt(e){return e instanceof i&&e.details?.[At]===!0}async function F(e){let t=await x(e.url.protocol),n=k.statSync(e.payloadPath).size,r=Ft(e.headers,e.startOffset,n);return Pt(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:r},t=>{s=!0,ge(t).then(r=>{clearTimeout(l);let s=t.statusCode??500,c=t.headers.location;if(c&&It(s)){if(e.redirectCount>=5){o(new i(`COMMAND_FAILED`,`Artifact upload exceeded redirect limit`,{maxRedirects:5,url:e.url.toString()}));return}let t=new URL(c,e.url);F({...e,url:t,redirectCount:e.redirectCount+1}).then(a,o);return}let u=Lt(s)?Rt(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 i(`COMMAND_FAILED`,`Artifact upload resume did not advance`,{offset:u,previousOffset:e.startOffset,url:e.url.toString()}));return}F({...e,startOffset:u}).then(a,o);return}a({statusCode:s,statusMessage:t.statusMessage,body:r})}).catch(o)}),l=setTimeout(()=>{c.destroy(),o(new i(`COMMAND_FAILED`,e.timeoutMessage,{timeoutMs:kt,...e.timeoutHint?{hint:e.timeoutHint}:{},...Nt(e)}))},kt);c.on(`error`,t=>{s||(clearTimeout(l),o(new i(`COMMAND_FAILED`,e.errorMessage,{...e.errorHint?{hint:e.errorHint}:{},...Nt(e)},t)))}),c.on(`close`,()=>clearTimeout(l)),A(k.createReadStream(e.payloadPath,{start:e.startOffset}),Ct({stage:e.progress?.stage??`legacy`,fileName:e.progress?.fileName??O.basename(e.payloadPath),startOffset:e.startOffset,totalBytes:n,onProgress:e.progress?.onProgress}),c).catch(e=>{s||(c.destroy(),o(new i(`COMMAND_FAILED`,`Failed to read local artifact`,{},e instanceof Error?e:Error(String(e)))))})})}function Nt(e){return e.retryable===!0?{[At]:!0}:{}}function Pt(e,t,n){e?.onProgress?.({type:t>0?`resume`:`start`,stage:e.stage,fileName:e.fileName,transferredBytes:t,totalBytes:n})}function Ft(e,t,n){return t<=0?e:{...e,"content-length":Math.max(n-t,0),"content-range":`bytes ${t}-${n-1}/${n}`}}function It(e){return[301,302,303,307,308].includes(e)}function Lt(e){return e===308}function Rt(e,t){let n=zt(e[`x-upload-offset`]??e[`upload-offset`]);if(n!==void 0)return Math.min(n,t);let r=Bt(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 zt(e){let t=Bt(e);if(t===void 0)return;let n=Number(t);return Number.isSafeInteger(n)&&n>=0?n:void 0}function Bt(e){return Array.isArray(e)?e[0]:e}const Vt=30*1e3;async function Ht(e){let t=await _t(e.localPath,e.platform),n=e.baseUrl.endsWith(`/`)?e.baseUrl:`${e.baseUrl}/`,r=qe();try{let i=await Kt({normalizedBase:n,token:e.token,artifact:t,uploadAttemptId:r});return i?.kind===`cache-hit`?i.uploadId:i?.kind===`direct-upload`?await Ut({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 Gt({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress})):await Gt({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress})}finally{t.cleanup()}}async function Ut(e){let t=async t=>(await Yt(e.artifact,t,e.onProgress),await Xt({normalizedBase:e.normalizedBase,token:e.token,uploadId:t.uploadId}));try{return await t(e.preflight)}catch(n){if(!Wt(n))return;let r=await Kt({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 Wt(e){return e instanceof i?Mt(e):!0}async function Gt(e){let{normalizedBase:t,token:n,artifact:r}=e,a=new URL(`upload`,t),o={"content-type":r.contentType,"x-artifact-type":r.artifactType,"x-artifact-filename":r.fileName,"x-artifact-hash":r.sha256,"x-artifact-hash-algorithm":`sha256`,"transfer-encoding":`chunked`};Object.assign(o,b(n));let s=await jt({url:a,method:`POST`,headers:o,payloadPath:r.payloadPath,timeoutMessage:`Artifact upload timed out`,timeoutHint:`The upload to the remote daemon exceeded the 5-minute timeout.`,errorMessage:`Failed to upload artifact to remote daemon`,errorHint:`Verify the remote daemon is reachable and supports artifact uploads.`,progress:{stage:`legacy`,fileName:r.fileName,onProgress:e.onProgress}});try{let e=JSON.parse(s.body);if(!e.ok||!e.uploadId)throw new i(`COMMAND_FAILED`,`Upload failed: ${s.body}`);return e.uploadId}catch(e){throw e instanceof i?e:new i(`COMMAND_FAILED`,`Invalid upload response: ${s.body}`)}}async function Kt(e){let t=new URL(`upload/preflight`,e.normalizedBase),n={"content-type":`application/json`};Object.assign(n,b(e.token));let r=await fetch(t,{method:`POST`,headers:n,signal:AbortSignal.timeout(Vt),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 qt(await r.json().catch(()=>void 0))}function qt(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(Jt(r))return{kind:`direct-upload`,uploadId:t.uploadId,url:n.url,headers:r}}function Jt(e){return!e||typeof e!=`object`||Array.isArray(e)?!1:Object.values(e).every(e=>typeof e==`string`)}async function Yt(e,t,n){let r=await jt({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(r.statusCode<200||r.statusCode>=300)throw new i(`COMMAND_FAILED`,`Direct artifact upload failed`,{statusCode:r.statusCode,statusMessage:r.statusMessage})}async function Xt(e){let t=new URL(`upload/finalize`,e.normalizedBase),n={"content-type":`application/json`};Object.assign(n,b(e.token));let r=await fetch(t,{method:`POST`,headers:n,signal:AbortSignal.timeout(Vt),body:JSON.stringify({uploadId:e.uploadId})}).catch(e=>{throw new i(`COMMAND_FAILED`,`Failed to finalize direct artifact upload`,{},e)});if(!r.ok)throw new i(`COMMAND_FAILED`,`Direct artifact upload finalize failed`,{status:r.status,statusText:r.statusText});let a=await r.json().catch(()=>void 0);if(!a?.ok||!a.uploadId)throw new i(`COMMAND_FAILED`,`Invalid upload finalize response`);return a.uploadId}async function Zt(e,t){let n=[...e.positionals??[]],r=e.flags?{...e.flags}:void 0,i=e.meta?.installSource,a={},o,s=wt();if(!hn(t))return rn({positionals:n,flags:r,installSource:i,uploadedArtifactId:o,clientArtifactPaths:a});Qt(e),r=en(e,n,r,a);let c=await an(e,t,s);return c&&(i=c.installSource,o=c.uploadedArtifactId??o),e.command!==`install`&&e.command!==`reinstall`||(o=await $t(e,t,n,s)??o),rn({positionals:n,flags:r,installSource:i,uploadedArtifactId:o,clientArtifactPaths:a})}function Qt(e){if(e.flags?.saveScript!==void 0)throw new i(`INVALID_ARGS`,`--save-script is not supported against a remote daemon: the healed script would be written on the daemon host, not on this machine.`,{hint:`Run the script against a local daemon to capture a healed .ad, or re-run without --save-script.`,command:e.command})}async function $t(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=nn(a,e.meta?.cwd);if(o)return await Ht({localPath:o,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:r})}function en(e,t,n,r){let i=on(e,t);if(!i)return n;i.positionalPath!==void 0&&(t[i.positionalIndex]=i.positionalPath);let a=tn(n,i.flagPath);return r[i.field]=i.localPath,a}function tn(e,t){return t===void 0?e:{...e??{},out:t}}function nn(e,t){let n=O.isAbsolute(e)?e:O.resolve(t??process.cwd(),e);return k.existsSync(n)?n:void 0}function rn(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 an(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=O.isAbsolute(i)?i:O.resolve(e.meta?.cwd??process.cwd(),i);if(!k.existsSync(a))return{installSource:{...r,path:a}};let o=await Ht({localPath:a,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:n});return{installSource:{...r,path:a},uploadedArtifactId:o}}function on(e,t){if(e.command===`screenshot`){let n=un(e,`path`,`.png`);return t[0]?{field:`path`,localPath:n,positionalIndex:0,positionalPath:L(`screenshot`,`.png`)}:{field:`path`,localPath:n,positionalIndex:0,flagPath:L(`screenshot`,`.png`)}}if(e.command===`record`&&(t[0]??``).toLowerCase()===`start`){if(!cn(e)&&e.flags?.platform===void 0)return null;let t=sn(e),n=ln(un(e,`outPath`,t,1),e);return{field:`outPath`,localPath:n,positionalIndex:1,positionalPath:L(`recording`,O.extname(n)||t)}}return null}function sn(e){return ze(e.flags?.platform)}function cn(e){return I(e.positionals?.[1])||I(e.flags?.out)}function ln(e,t){return t.flags?.platform===`web`?Be(e,sn(t)):e}function un(e,t,n,r=0){let i=e.positionals?.[r]??e.flags?.out,a=`${t===`path`?`screenshot`:`recording`}-${Date.now()}${n}`,o=I(i)?i:a;return O.isAbsolute(o)?o:O.resolve(e.meta?.cwd??process.cwd(),o)}function I(e){return typeof e==`string`&&e.trim().length>0}function L(e,t){let n=t.startsWith(`.`)?t:`.${t}`;return O.posix.join(`/tmp`,`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}${n}`)}async function dn(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=fn(n,t);await pn({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 fn(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 O.resolve(t.meta?.cwd??process.cwd(),r)}async function pn(e){let t=new URL(mn(e.baseUrl,e.artifactId)),n=await x(t.protocol);await k.promises.mkdir(O.dirname(e.destinationPath),{recursive:!0}),await new Promise((r,a)=>{let o=!1,s=e.timeoutMs??9e4,c=t=>{if(!o){if(o=!0,clearTimeout(u),t){k.promises.rm(e.destinationPath,{force:!0}).finally(()=>a(t));return}r()}},l=n.request({protocol:t.protocol,host:t.hostname,port:t.port,method:`GET`,path:t.pathname+t.search,headers:{...b(e.token),...we(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 i(`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 i(`COMMAND_FAILED`,`Remote artifact download was interrupted`,{artifactId:e.artifactId,requestId:e.requestScope?.requestId}))}),A(t,k.createWriteStream(e.destinationPath)).then(()=>c(),e=>c(e instanceof Error?e:Error(String(e))))}),u=setTimeout(()=>{let t=new i(`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 i){c(t);return}c(new i(`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 mn(e,t){let n=e.endsWith(`/`)?e:`${e}/`;return new URL(`artifacts/${encodeURIComponent(t)}`,n).toString()}function hn(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}const gn=3e3,_n=1e3;function vn(e){let t=On(e);if(!t||typeof t!=`object`)return null;let n=t,r=yn(n);if(!r)return null;let i=bn(n);return i?{token:r,...i,transport:xn(n.transport),pid:R(n.pid)??0,version:Sn(n.version),codeSignature:Sn(n.codeSignature),processStartTime:Sn(n.processStartTime)}:null}function yn(e){return typeof e.token==`string`&&e.token.length>0?e.token:null}function bn(e){let t=R(e.port),n=R(e.httpPort);return t===void 0&&n===void 0?null:{port:t,httpPort:n}}function xn(e){return e===`socket`||e===`http`||e===`dual`?e:void 0}function Sn(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=On(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){kn(e)}function V(e){kn(e)}function Cn(e){let t=U(e);if(!t.hasLock||t.hasInfo)return;let n=z(e.lockPath);if(!n){V(e.lockPath);return}y(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=k.existsSync(e.infoPath),n=vn(e.infoPath);if(n){let t=y(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=k.existsSync(e.lockPath),o=z(e.lockPath);if(o){let t=y(o.pid,o.processStartTime);t&&!r?i.retainedLockProcess=!0:(t&&(await ye(o.pid,{termTimeoutMs:gn,killTimeoutMs:_n,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 T({level:i.error?`warn`:`info`,phase:`daemon_startup_metadata_cleanup`,data:i}),i}function U(e){return{hasInfo:k.existsSync(e.infoPath),hasLock:k.existsSync(e.lockPath)}}async function wn(e){let t=U(e);if(!t.hasLock||t.hasInfo)return!1;let n=z(e.lockPath);return!n||!y(n.pid,n.processStartTime)?(V(e.lockPath),!0):!1}async function W(e){await ye(e.pid,{termTimeoutMs:gn,killTimeoutMs:_n,expectedStartTime:e.processStartTime})}function Tn(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}function En(e,t=v(process.env.AGENT_DEVICE_STATE_DIR)){let n=Dn(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 Dn(e){return`rm -f ${Ue(e.infoPath)} ${Ue(e.lockPath)}`}function On(e){if(!k.existsSync(e))return null;try{return JSON.parse(k.readFileSync(e,`utf8`))}catch{return null}}function kn(e){try{k.existsSync(e)&&k.unlinkSync(e)}catch{}}function An(e,t){if(t.onProgress){t.onProgress(e);return}e.type===`command`&&(t.req.command===`doctor`&&fe(),process.stderr.write(`${e.message}\n`))}function G(e,t,n){return new i(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:e.meta?.requestId,line:t},n instanceof Error?n:void 0)}function jn(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(be(r))try{return An(r.event,{req:e.req,onProgress:e.onProgress}),!1}catch(e){return t(e)}return _e(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 Mn(e,t){return xe(e)&&String(Array.isArray(t)?t.join(`,`):t??``).includes(`application/x-ndjson`)}function Nn(e,t){let{req:n,isSettled:r,resolve:i,reject:a,clearTimeout:o}=t,s=``,c=jn({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=Te(s,e);s=t.buffer;for(let e of t.lines)if(c.handleLine(e))return})}function Pn(e,t){let{req:n,handleResponseBody:r,reject:a,clearTimeout:o}=t,s=``,c=!1,l=jn({req:n,onProgress:t.onProgress,responseFormat:`ndjson-envelope`,onResponse(e){c=!0,o(),r(JSON.stringify(e))},onError(e){c=!0,o(),a(e)}});e.setEncoding(`utf8`),e.on(`data`,e=>{if(c)return;let t=Te(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 i(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:n.meta?.requestId},e instanceof Error?e:void 0)))})}const Fn=1e4,In=8*1024*1024;function Ln(e,t){return S(e,`sessions/${encodeURIComponent(t.session)}/requests/${encodeURIComponent(t.requestId)}/diagnostics`)}function Rn(e){let{logPath:t,...n}=e;return n}async function zn(e,t){let n=Rn(e),r=e.diagnosticsRecord,i=r?.requestId??t.requestId;if(!r)return K(n,t.endpoint,i,`the daemon named no diagnostics record`);try{let e=me(t.stateDir,r),a=await Bn({endpoint:t.endpoint,ref:r,destinationPath:e});return a?K(n,t.endpoint,i,a):{...n,logPath:e}}catch(e){return K(n,t.endpoint,i,e instanceof Error?e.message:String(e))}}function K(e,t,n,r){return{...e,logPathUnavailable:`remote daemon ${t.baseUrl}, request ${n??`unknown`}: ${r}`}}async function Bn(e){let{endpoint:t,ref:n,destinationPath:r}=e,i;try{i=new URL(Ln(t.baseUrl,n))}catch{return`daemon base URL is not a valid URL`}try{let e=await x(i.protocol);return await k.promises.mkdir(O.dirname(r),{recursive:!0}),await new Promise(n=>{let a=!1,o=e=>{if(!a){if(a=!0,clearTimeout(c),e===void 0){n(void 0);return}k.promises.rm(r,{force:!0}).finally(()=>{n(e)})}},s=e.request({protocol:i.protocol,host:i.hostname,port:i.port,method:`GET`,path:i.pathname+i.search,headers:{...b(t.token),...we(t.tenantId)}},e=>{let t=e.statusCode??500;if(t!==200){e.resume(),o(`HTTP ${t}`);return}let n=k.createWriteStream(r),i=0;e.on(`data`,e=>{i+=e.length,i>In&&(s.destroy(),n.destroy(),o(`record exceeds ${In} bytes`))}),e.on(`error`,e=>{n.destroy(),o(e.message)}),n.on(`error`,e=>{o(e.message)}),n.on(`finish`,()=>{o(void 0)}),e.pipe(n)}),c=setTimeout(()=>{o(`fetch timed out after ${Fn}ms`),s.destroy()},Fn);s.on(`error`,e=>{o(e.message)}),s.end()})}catch(e){return e instanceof Error?e.message:String(e)}}function Vn(e,t){let{info:n,req:r,stateDir:a,resolve:o,reject:s}=t;try{let t=Hn(e);if(t.error){Un(t.error,{info:n,req:r,stateDir:a,reject:s});return}if(!t.result||typeof t.result!=`object`){s(new i(`COMMAND_FAILED`,`Invalid daemon RPC response`,{requestId:r.meta?.requestId}));return}Kn(n,r,t.result,o,s)}catch(t){s(new i(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:r.meta?.requestId,line:e},t instanceof Error?t:void 0))}}function Hn(e){return JSON.parse(e)}async function Un(e,t){let{info:n,req:r,stateDir:i,reject:a}=t,o=r.meta?.requestId,s=Wn(e);if(!n.baseUrl){a(Gn(s,o));return}a(Gn(await zn(s,{endpoint:{baseUrl:n.baseUrl,token:n.token,tenantId:r.meta?.tenantId},stateDir:i,requestId:o}),o))}function Wn(e){let r=e.data??{};return{code:t(r.code==null?void 0:String(r.code),`COMMAND_FAILED`),message:String(r.message??e.message??`Daemon RPC request failed`),details:typeof r.details==`object`&&r.details?r.details:void 0,hint:typeof r.hint==`string`?r.hint:void 0,diagnosticId:typeof r.diagnosticId==`string`?r.diagnosticId:void 0,logPath:typeof r.logPath==`string`?r.logPath:void 0,diagnosticsRecord:n(r.diagnosticsRecord),retriable:typeof r.retriable==`boolean`?r.retriable:void 0,supportedOn:typeof r.supportedOn==`string`?r.supportedOn:void 0}}function Gn(e,n){return new i(t(e.code,`COMMAND_FAILED`),e.message,{...e.details??{},hint:e.hint,diagnosticId:e.diagnosticId,logPath:e.logPath,logPathUnavailable:e.logPathUnavailable,diagnosticsRecord:e.diagnosticsRecord,retriable:e.retriable,supportedOn:e.supportedOn,requestId:n})}async function Kn(e,t,n,r,i){try{r(e.baseUrl&&n.ok?await dn(e,t,n):n)}catch(e){i(e)}}function qn(e,t){let n=e.meta?.requestId??Re();return Jn(e.command)?{jsonrpc:`2.0`,id:n,method:Yn(e.command),params:Xn(e,e.command,t)}:{jsonrpc:`2.0`,id:n,method:`agent_device.command`,params:e}}function Jn(e){return e===`lease_allocate`||e===`lease_heartbeat`||e===`lease_release`}function Yn(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 Xn(e,t,n){return ce(ue(e),t,{includeTokenParam:n.includeTokenParam,token:e.token,session:e.session})}const Zn=[`xcodebuild .*AgentDeviceRunnerUITests/RunnerTests/testCommand`,`xcodebuild .*AgentDeviceRunner\\.env\\.session-`,`xcodebuild build-for-testing .*apple/runner/AgentDeviceRunner/AgentDeviceRunner\\.xcodeproj`],Qn=new Set([`apple`,`ios`,`macos`]);function $n(e){return e!==void 0&&Qn.has(e)}function er(e){let t=u(e.command);if(t.envelopeMs===`unbounded`)return;let n={...t,envelopeMs:t.envelopeMs};return tr(n,e.positionals??[])??nr(n,e.flags)??n.envelopeMs}function tr(e,t){if(e.budget.source!==`positional-parser`)return;let n=e.budget.parser(t);return n===null?void 0:ir(e,n)}function nr(e,t){if(e.budget.source===`flag`)return e.budget.envelope===`widen`?rr(e,e.budget,t):typeof t?.timeoutMs==`number`?t.timeoutMs:e.envelopeMs}function rr(e,t,n){if(n?.settle!==!0)return e.envelopeMs;let r=typeof n.timeoutMs==`number`?n.timeoutMs:t.defaultBudgetMs;return typeof r==`number`?ar(e,r):e.envelopeMs}function ir(e,t){return Math.max(e.envelopeMs,t+re)}function ar(e,t){return Math.max(e.envelopeMs,e.envelopeMs+t+re)}function or(e,t,n,r,a,o,s){let c=a?{terminated:0}:lr(),l=!a&&sr(r),u=l?ur(e,t):{forcedKill:!1},d=$n(s)||c.terminated>0;return T({level:`error`,phase:`daemon_request_timeout`,data:{timeoutMs:o,requestId:n,command:r,timedOutRunnerPidsTerminated:c.terminated,timedOutRunnerCleanupError:c.error,daemonPidReset:l?e.pid:void 0,daemonPidForceKilled:l?u.forcedKill:void 0,daemonPreservedAfterTimeout:!a&&!l,daemonBaseUrl:e.baseUrl}}),new i(`COMMAND_FAILED`,`Daemon request timed out`,{timeoutMs:o,requestId:n,hint:cr({remote:a,resetDaemon:l,command:r,appleCleanupEvidence:d})})}function sr(e){return u(e).onTimeout===`reset-daemon`}function cr(e){let{remote:t,resetDaemon:n,command:r,appleCleanupEvidence:i}=e;if(t)return`Retry with --debug and verify the remote daemon URL, auth token, and remote host logs.`;if(!n){let e=i&&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${i?` and Apple runner work was aborted when detected`:``}; the daemon was kept alive so the session can still be closed or inspected.${e}`}return i?`Retry with --debug and check daemon diagnostics logs. Timed-out Apple runner xcodebuild processes were terminated when detected.`:`Retry with --debug and check daemon diagnostics logs. The daemon was reset after the timeout.`}function lr(){let e=0;try{for(let t of Zn)Fe(`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 ur(e,t){let n=!1;try{y(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 dr=`Daemon HTTP endpoint is unavailable`,fr=`Daemon socket endpoint is unavailable`;async function pr(e,t){let n=Sr(e,t);if(await mr(e,n))return!0;let r=Cr(e,t,n);return r?await mr(e,r):!1}async function mr(e,t){return t===`http`?await gr(e):await hr(e.port)}function hr(e){return e?new Promise(t=>{let n=!1,r=j.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 gr(e){return vr(e).then(e=>e.reachable)}async function _r(e){let t=await vr(e);if(!e.baseUrl||!t.reachable)return t;if(typeof t.rpcProtocolVersion==`number`&&t.rpcProtocolVersion!==2)throw new i(`COMMAND_FAILED`,`Remote daemon RPC protocol is incompatible`,{daemonBaseUrl:e.baseUrl,clientVersion:E(),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}async function vr(e){let t=e.baseUrl?S(e.baseUrl,`health`):e.httpPort?`http://127.0.0.1:${e.httpPort}/health`:null;if(!t)return{reachable:!1};let n=new URL(t),r=await x(n.protocol),i=e.baseUrl?3e3:500;return await new Promise(t=>{let a=e.baseUrl?b(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,...yr(n)})})});o.on(`timeout`,()=>{o.destroy(),t({reachable:!1})}),o.on(`error`,()=>{t({reachable:!1})}),o.end()})}function yr(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 br(e,t,n,r,i,a={}){let o=Sr(e,n);try{return await xr(e,t,r,i,o,a)}catch(s){let c=Cr(e,n,o);if(!c||!wr(s,o))throw s;return await xr(e,t,r,i,c,a)}}async function xr(e,t,n,r,i,a){return i===`http`?await Or(e,t,n,r,a):await Dr(e,t,n,r,a)}function Sr(e,t){if(e.baseUrl){if(t===`socket`)throw new i(`COMMAND_FAILED`,`Remote daemon endpoint only supports HTTP transport`,{daemonBaseUrl:e.baseUrl});return`http`}if(t===`http`||t===`socket`)return Tr(e,t);let n=(e.transport===`socket`||e.transport===`dual`?[`socket`,`http`]:[`http`,`socket`]).find(t=>q(e,t));if(n)return n;throw new i(`COMMAND_FAILED`,`Daemon metadata has no reachable transport`)}function q(e,t){return t===`http`?!!e.httpPort:!!e.port}function Cr(e,t,n){if(t!==`auto`||e.baseUrl)return null;let r=n===`socket`?`http`:`socket`;return q(e,r)?r:null}function wr(e,t){return t===`socket`&&e instanceof i&&e.code===`COMMAND_FAILED`&&e.message===`Failed to communicate with daemon`&&e.details?.daemonSocketRequestWritten===!1}function Tr(e,t){if(q(e,t))return t;throw new i(`COMMAND_FAILED`,t===`http`?dr:fr)}function Er(e,t,n,r={}){return T({level:`error`,phase:`daemon_request_socket_error`,data:{requestId:t,message:e instanceof Error?e.message:String(e)}}),new i(`COMMAND_FAILED`,`Failed to communicate with daemon`,{...r,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 Dr(e,t,n,r,a){let o=e.port;if(!o)throw new i(`COMMAND_FAILED`,fr);return new Promise((i,s)=>{let c=!1,l=j.createConnection({host:`127.0.0.1`,port:o},()=>{c=!0,l.write(`${JSON.stringify(t)}\n`)}),u=!1,d=typeof r==`number`?setTimeout(()=>{u=!0,l.destroy(),s(or(e,n,t.meta?.requestId,t.command,!1,r,t.flags?.platform))},r):void 0;Nn(l,{req:t,onProgress:a.onProgress,isSettled:()=>u,clearTimeout:()=>{d&&clearTimeout(d)},resolve:e=>{u=!0,i(e)},reject:e=>{u=!0,s(e)}}),l.on(`error`,e=>{u||(u=!0,d&&clearTimeout(d),s(Er(e,t.meta?.requestId,!1,{daemonSocketRequestWritten:c})))})})}async function Or(e,t,n,r,a){let o=e.baseUrl?new URL(S(e.baseUrl,`rpc`)):e.httpPort?new URL(`http://127.0.0.1:${e.httpPort}/rpc`):null;if(!o)throw new i(`COMMAND_FAILED`,dr);let s=JSON.stringify(qn(t,{includeTokenParam:!e.baseUrl})),c={"content-type":`application/json`,"content-length":Buffer.byteLength(s)};e.baseUrl&&Object.assign(c,b(e.token));let l=await x(o.protocol);return await new Promise((u,d)=>{let f=l.request({protocol:o.protocol,host:o.hostname,port:o.port,method:`POST`,path:o.pathname+o.search,headers:c},r=>{if(Mn(t,r.headers?.[`content-type`])){Pn(r,{req:t,onProgress:a.onProgress,reject:d,clearTimeout:()=>{m&&clearTimeout(m)},handleResponseBody:r=>Vn(r,{info:e,req:t,stateDir:n.baseDir,resolve:u,reject:d})});return}ge(r).then(r=>{m&&clearTimeout(m),Vn(r,{info:e,req:t,stateDir:n.baseDir,resolve:u,reject:d})}).catch(e=>{m&&clearTimeout(m),d(new i(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:t.meta?.requestId},e instanceof Error?e:void 0))})}),p=Tn(e),m=typeof r==`number`?setTimeout(()=>{f.destroy(),d(or(e,n,t.meta?.requestId,t.command,p,r,t.flags?.platform))},r):void 0;f.on(`error`,e=>{m&&clearTimeout(m),d(Er(e,t.meta?.requestId,p))}),f.write(s),f.end()})}const J=15e3,Y=new j.BlockList;Y.addSubnet(`127.0.0.0`,8,`ipv4`),Y.addAddress(`::1`,`ipv6`),Y.addSubnet(`::ffff:127.0.0.0`,104,`ipv6`);function kr(e,t){let n=Ar(e),r=jr(e,t),i=Mr(e,r.remoteBaseUrl),a=Nr(e,n,r.rawBaseUrl);return{paths:v(a?Pr():n),transportPreference:i.preference,serverMode:i.serverMode,ownedStateDir:a,remoteBaseUrl:r.remoteBaseUrl,remoteAuthToken:r.authToken}}function Ar(e){return e.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR}function jr(e,t){let n=e.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL,r=ri(n),i=t??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN;return ii(r,i),{rawBaseUrl:n,remoteBaseUrl:r,authToken:i}}function Mr(e,t){let n=e.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,r=De(n);if(t&&r===`socket`)throw new i(`INVALID_ARGS`,`Remote daemon base URL only supports HTTP transport. Remove --daemon-transport socket.`,{daemonBaseUrl:t});return{preference:r,serverMode:Ee(e.flags?.daemonServerMode??process.env.AGENT_DEVICE_DAEMON_SERVER_MODE??(n===`dual`?`dual`:void 0))}}function Nr(e,t,n){return Jr(e.command)&&!t&&!n}function Pr(){return k.mkdtempSync(O.join(Je.tmpdir(),`agent-device-replay-daemon-`))}async function Fr(e){if(e.remoteBaseUrl)return await Ir(e);let t=await Lr(e);return t?{info:t,startedByClient:!1}:(Cn(e.paths),await Ur(e))}async function Ir(e){let t={transport:`http`,token:e.remoteAuthToken??``,pid:0,baseUrl:e.remoteBaseUrl};if((await _r(t)).reachable)return{info:t,startedByClient:!1};throw new i(`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 Lr(e){let t=vn(e.paths.infoPath);if(!t)return null;let n=await Rr(t,e.transportPreference);return Br(t,n)?t:(Vr(t,n,e.paths.baseDir),await W(t),B(e.paths.infoPath),null)}async function Rr(e,t){try{return await pr(e,t)}catch(e){if(zr(e))return!1;throw e}}function zr(e){return e instanceof i&&e.code===`COMMAND_FAILED`&&(e.message===`Daemon HTTP endpoint is unavailable`||e.message===`Daemon socket endpoint is unavailable`)}function Br(e,t){return e.version===E()&&e.codeSignature===ei()&&t}function Vr(e,t,n){try{let r=e.version?`pid ${e.pid}, v${e.version}`:`pid ${e.pid}`,i=Hr(e,t);process.stderr.write(`Replacing daemon (${r}) in ${n}: ${i}\n`)}catch{}}function Hr(e,t){return e.version===E()?e.codeSignature===ei()?t?`not reusable`:`unreachable`:`code-signature mismatch`:`version mismatch (client v${E()})`}async function Ur(e){let t=0,n=[],r,a;for(let i=1;i<=2;i+=1){let o;try{o=Qr(e),a={pid:o.pid}}catch(t){if(r=t instanceof Error?t.message:String(t),n.push(await H(e.paths,`start_error`)),i<2){await D(150);continue}break}let s=await Zr(J,e,o);if(s.kind===`ready`)return{info:s.info,startedByClient:!0};if(s.kind===`early_exit`){if(a=s.exit,r=ti(s.exit),n.push(await H(e.paths,`start_error`)),i<2){await D(150);continue}break}if(await wn(e.paths)){t+=1;continue}let c=U(e.paths),l=i<2,u=await H(e.paths,`startup_timeout`,{stopLiveProcesses:!1});if(n.push(u),u.retainedInfoProcess||u.retainedLockProcess){let t=await Zr(J,e,o);if(t.kind===`ready`)return{info:t.info,startedByClient:!0};t.kind===`early_exit`&&(a=t.exit,r=ti(t.exit));break}if(!l)break;!c.hasInfo&&!c.hasLock&&await D(150)}let o=U(e.paths),s=ni(e.paths.logPath);throw new i(`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:J,startupAttempts:2,lockRecoveryCount:t,cleanupResults:n,startError:r,daemonProcess:a,...s?{daemonLogTail:s}:{},metadataState:o,hint:En(o,e.paths)})}async function Wr(e,t,n,r){if(!Jr(e.command)||!t.startedByClient&&!n.ownedStateDir||Tn(t.info)||Kr(r)||Yr(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=k.existsSync(n.paths.infoPath);B(n.paths.infoPath),i.removedInfo=e&&!k.existsSync(n.paths.infoPath);let t=k.existsSync(n.paths.lockPath);if(V(n.paths.lockPath),i.removedLock=t&&!k.existsSync(n.paths.lockPath),n.ownedStateDir){let e=he(n.paths.sessionsDir);e?a=Gr(r,e):(k.rmSync(n.paths.baseDir,{recursive:!0,force:!0}),i.removedStateDir=!k.existsSync(n.paths.baseDir))}}return T({level:i.error?`warn`:`info`,phase:`daemon_replay_cleanup`,data:i}),a}function Gr(e,t){if(e&&!e.ok)return e;let{sessionName:n,tombstone:a}=t,o=a.sourcePath?`re-run: replay ${a.sourcePath} --save-script`:`re-run your replay <script> --save-script from the start`;return{ok:!1,error:r(new i(`REPAIR_COMMIT_FAILED`,`The repair transaction for session "${n}" completed, but committing its healed script failed at teardown: ${a.commitFailure.message}. ${o}.`))}}function Kr(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 qr(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 Jr(e){return e===C.replay||e===C.test}function Yr(e,t){return e.command!==C.replay||!t||!t.ok?!1:t.data?.sessionActive===!0}function Xr(e,t){let n=e.data??{},r=typeof n.session==`string`?n.session:void 0,i=[...t?[`--state-dir ${He(t)}`]:[],...r?[`--session ${He(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 Zr(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=vn(t.paths.infoPath);if(e&&await pr(e,t.transportPreference))return{kind:`ready`,info:e};if(i)return{kind:`early_exit`,exit:i};await D(100)}return{kind:`timeout`}}function Qr(e){let t=$r(),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};k.mkdirSync(e.paths.baseDir,{recursive:!0});let i=k.openSync(e.paths.logPath,`a`),a=k.openSync(e.paths.logPath,`a`);try{return Le(process.execPath,n,{env:r,stdio:[`ignore`,i,a]})}finally{k.closeSync(i),k.closeSync(a)}}function $r(){let e=Ve(),t=[O.join(e,`dist`,`src`,`internal`,`daemon.js`),O.join(e,`dist`,`src`,`daemon.js`)],n=t[0];if(n===void 0)throw new i(`COMMAND_FAILED`,`Daemon dist path list is empty`);let r=t.find(e=>k.existsSync(e))??n,a=O.join(e,`src`,`daemon.ts`),o=t.some(e=>k.existsSync(e)),s=k.existsSync(a);if(!o&&!s)throw new i(`COMMAND_FAILED`,`Daemon entry not found`,{distPaths:t,srcPath:a});return{root:e,distPath:r,distPaths:t,srcPath:a,useSrc:(process.execArgv.includes(`--experimental-strip-types`)||!o)&&s}}function ei(){let e=$r();return Se(e.useSrc?e.srcPath:e.distPath,e.root)}function ti(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 ni(e){try{if(!k.existsSync(e))return;let t=k.statSync(e);if(t.size<=0)return;let n=Math.min(t.size,64e3),r=k.openSync(e,`r`);try{let e=Buffer.alloc(n);k.readSync(r,e,0,n,t.size-n);let i=e.toString(`utf8`).trim();return i.length>0?i:void 0}finally{k.closeSync(r)}}catch{return}}function ri(e){if(!e)return;let t;try{t=new URL(e)}catch(t){throw new i(`INVALID_ARGS`,`Invalid daemon base URL`,{daemonBaseUrl:e},t instanceof Error?t:void 0)}if(t.protocol!==`http:`&&t.protocol!==`https:`)throw new i(`INVALID_ARGS`,`Daemon base URL must use http or https`,{daemonBaseUrl:e});return t.toString().replace(/\/+$/,``)}function ii(e,t){if(!e)return;let n=new URL(e).hostname;if(!ai(n)&&!(typeof t==`string`&&t.trim().length>0))throw new i(`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 ai(e){let t=e.trim().toLowerCase().replace(/^\[(.*)\]$/,`$1`);return t===`localhost`?!0:j.isIPv4(t)?Y.check(t,`ipv4`):j.isIPv6(t)?Y.check(t,`ipv6`):!1}async function oi(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=kr(s,t.authToken??a),l=er(s),u=await Pe(`daemon_startup`,async()=>await Fr(c),{requestId:n,session:e.session}),d=u.info,f=await Zt(s,d);mi(s.command);let p=si(s,f,d.token,n,r);return T({level:`info`,phase:`daemon_request_prepare`,data:{requestId:n,command:s.command,session:s.session}}),await di(s,u,c,async()=>pi(fi(await Pe(`daemon_request`,async()=>await br(d,p,c.transportPreference,c.paths,l,t.onProgress?{onProgress:t.onProgress}:void 0),{requestId:n,command:e.command}),c),s,c))}function si(e,t,n,r,i){return{...e,positionals:t.positionals,flags:t.flags,token:n,meta:ci(e,t,r,i)}}function ci(e,t,n,r){let i=e.meta??{};return{...i,requestId:n,debug:r,...li(i,e.flags),...ui(t)}}function li(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 ui(e){return{...e.uploadedArtifactId?{uploadedArtifactId:e.uploadedArtifactId}:{},...e.clientArtifactPaths?{clientArtifactPaths:e.clientArtifactPaths}:{},...e.installSource?{installSource:e.installSource}:{}}}async function di(e,t,n,r){let a,o=!1,s;try{a=await r()}catch(e){o=!0,s=e}let c=await Wr(e,t,n,a);if(o)throw s;if(!c)throw new i(`COMMAND_FAILED`,`Daemon request produced no response after cleanup`);return c}function fi(e,t){return e.ok||!t.ownedStateDir||!Kr(e)?e:qr(e,t.paths.baseDir)}function pi(e,t,n){return!e.ok||!Yr(t,e)?e:Xr(e,n.ownedStateDir?n.paths.baseDir:void 0)}function mi(e){!hi(e)||process.stderr.isTTY!==!0||process.env.CI||process.stderr.write(e===C.reinstall?`Reinstalling...
|
|
2
2
|
`:`Installing...
|
|
3
|
-
`)}function
|
|
3
|
+
`)}function hi(e){return e===C.install||e===C.reinstall||e===w.installSource}function X(e,t){return O.join(e,`metro-sessions`,`${ve(t)}.json`)}function gi(e){let t=X(e.stateDir,e.session);k.mkdirSync(O.dirname(t),{recursive:!0}),k.writeFileSync(t,`${JSON.stringify(e.hints,null,2)}\n`,`utf8`)}function _i(e){let t=X(e.stateDir,e.session),n;try{n=k.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 vi(e){k.rmSync(X(e.stateDir,e.session),{force:!0})}var yi=e({createAgentDeviceClient:()=>bi});function bi(e={},t={}){let n=t.transport??oi,r=t=>a(t.responseLevel??e.responseLevel),s=async(t,r=[],i={},a,s)=>{let c=Q(e,i),l={session:N(c.session),command:t,positionals:r,...s?{input:s}:{},flags:Me(c,a),runtime:c.runtime,meta:ft(c)},u=await n(l,{authToken:c.daemonAuthToken});return u.ok||o(u.error),u.data??{}},c=async(e={})=>{let t=await s(w.sessionList,[],e);return(Array.isArray(t.sessions)?t.sessions:[]).map(tt)},l=async(e,t={})=>{let n=await ht(e,t);return await s(n.command,n.positionals,n.options,n.metadataFlags,n.input)},u=(t={})=>N(Q(e,t).session);return{command:{wait:async e=>await l(`wait`,e),alert:async(e={})=>await l(`alert`,e),...ji(l),reactNative:async e=>await l(`react-native`,e),doctor:async(e={})=>await l(`doctor`,e),prepare:async e=>await l(`prepare`,e),viewport:async e=>await l(`viewport`,e)},devices:{list:async(e={})=>{let t=await l(`devices`,e);return(Array.isArray(t.devices)?t.devices:[]).map(et)},capabilities:async(e={})=>{let t=await l(`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 l(`boot`,e),shutdown:async(e={})=>await l(`shutdown`,e)},sessions:{list:async(e={})=>await c(e),stateDir:async(t={})=>v(Q(e,t).stateDir??process.env.AGENT_DEVICE_STATE_DIR).baseDir,close:async(t={})=>{let n=u(t);try{let e=await l(`close`,t);return{session:n,shutdown:st(e.shutdown),provider:Z(e.provider),savedScript:f(e,`savedScript`),identifiers:{session:n}}}finally{Ii(e,t)}},saveScript:async(e={})=>{let t=await s(w.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 i(`COMMAND_FAILED`,`Daemon returned an invalid saved-script action count.`);let r=h(t,`session`);return{session:r,savedScript:h(t,`savedScript`),actionCount:n,identifiers:{session:r}}},artifacts:async(e={})=>await l(`artifacts`,e)},apps:{install:async e=>Ze(await l(`install`,e),u(e)),reinstall:async e=>Ze(await l(`reinstall`,e),u(e)),installFromSource:async e=>Qe(await l(`install-from-source`,e),u(e)),list:async(e={})=>{let t=await l(`apps`,e);return Array.isArray(t.apps)?t.apps.filter(e=>typeof e==`string`):[]},open:async t=>{let n=u(t),r=await l(`open`,t);Fi({config:e,options:t,runtime:Q(e,t).runtime,sessionReused:r.sessionReused===!0});let i=at(r),a=f(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:f(r,`sessionStateDir`),runnerLogPath:f(r,`runnerLogPath`),requestLogPath:f(r,`requestLogPath`),eventLogPath:f(r,`eventLogPath`),appName:f(r,`appName`),appBundleId:a,appId:o,startup:ot(r.startup),runtime:it(r.runtime),device:i,...ut(r),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=u(e),n=await l(`close`,e);return{session:t,closedApp:e.app,shutdown:st(n.shutdown),savedScript:f(n,`savedScript`),identifiers:{session:t}}},push:async e=>await l(`push`,e),triggerEvent:async e=>await l(`trigger-app-event`,e)},materializations:{release:async e=>$e(await s(w.releaseMaterializedPaths,[],{...e,materializationId:e.materializationId}))},leases:{allocate:async e=>Li(await s(w.leaseAllocate,[],{...e,leaseId:void 0})),heartbeat:async e=>Li(await s(w.leaseHeartbeat,[],e)),release:async e=>{let t=await s(w.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 Mi(e,n),n},reload:async(t={})=>await We({metroHost:t.metroHost,metroPort:t.metroPort,bundleUrl:t.bundleUrl,runtime:e.runtime??Ni(e),timeoutMs:t.timeoutMs})},capture:{snapshot:async(e={})=>{let t=u(e),n=await l(`snapshot`,e);return r(e)?n:ki(n,t)},screenshot:async(e={})=>{let t=u(e),n=await l(`screenshot`,e);if(r(e))return n;let i=Ce(n);return{path:h(n,`path`),width:i?.width,height:i?.height,logicalWidth:i?.logicalWidth,logicalHeight:i?.logicalHeight,pixelDensity:i?.pixelDensity,overlayRefs:i?.overlayRefs,identifiers:{session:t}}},diff:async e=>await l(`diff`,e)},interactions:{click:async e=>await l(`click`,e),press:async e=>await l(`press`,e),longPress:async e=>await l(`longpress`,e),hover:async e=>await l(`hover`,e),swipe:async e=>await l(`swipe`,e),pan:async e=>await l(`gesture`,xi(e)),drag:async e=>await l(`gesture`,Si(e)),fling:async e=>await l(`gesture`,Ci(e)),swipeGesture:async e=>await l(`gesture`,wi(e)),focus:async e=>await l(`focus`,e),type:async e=>await l(`type`,e),fill:async e=>await l(`fill`,e),scroll:async e=>await l(`scroll`,e),pinch:async e=>await l(`gesture`,Ti(e)),rotateGesture:async e=>await l(`gesture`,Ei(e)),transformGesture:async e=>await l(`gesture`,Di(e)),get:async e=>await l(`get`,e),is:async e=>await l(`is`,e),find:async e=>await l(`find`,e)},replay:{run:async e=>await l(`replay`,e),test:async e=>await l(`test`,e)},batch:{run:async e=>await l(`batch`,e)},observability:{perf:async(e={})=>await l(`perf`,e),logs:async(e={})=>await l(`logs`,e),events:async(e={})=>await l(`events`,e),network:async(e={})=>await l(`network`,e),audio:async(e={})=>await l(`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 l(`record`,e),trace:async e=>await l(`trace`,e)},settings:{update:async e=>await l(`settings`,e)}}}function xi(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 wi(e){return{...e,kind:`swipe`}}function Ti(e){let{x:t,y:n,...r}=e;return Oi(t,n,`pinch`),{...r,kind:`pinch`,...t===void 0&&n===void 0?{}:{origin:{x:t,y:n}}}}function Ei(e){let{x:t,y:n,...r}=e;return Oi(t,n,`rotate`),{...r,kind:`rotate`,...t===void 0&&n===void 0?{}:{origin:{x:t,y:n}}}}function Di(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 Oi(e,t,n){if(e===void 0!=(t===void 0))throw new i(`INVALID_ARGS`,`gesture ${n} center requires both x and y`)}function ki(e,t){let n=f(e,`appBundleId`);return{nodes:dt(e.nodes),truncated:e.truncated===!0,appName:f(e,`appName`),appBundleId:n,...Ai(e),identifiers:{session:t,appId:n,appBundleId:n}}}function Ai(e){let t=Z(e.visibility),n=Z(e.unchanged),r=c(e.snapshotDiagnostics);return{...t?{visibility:t}:{},...s(e),...n?{unchanged:n}:{},...r?{snapshotDiagnostics:r}:{},...typeof e.fallbackScreenshotPath==`string`?{fallbackScreenshotPath:e.fallbackScreenshotPath}:{},...typeof e.refsGeneration==`number`?{refsGeneration:e.refsGeneration}:{}}}function ji(e){let t={};for(let[n,r]of Object.entries(ke.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 g(e)?e:void 0}function Q(e,t){return{...e,...t}}function $(e,t={}){let n=Q(e,t);return{stateDir:v(n.stateDir??process.env.AGENT_DEVICE_STATE_DIR).baseDir,session:N(n.session)}}function Mi(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;gi({...$(e),hints:{metroHost:n.hostname,metroPort:r,bundleUrl:i}})}catch{}}function Ni(e){try{return _i($(e))}catch{return}}function Pi(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 Fi(e){try{let t=$(e.config,e.options),n=Pi(e.runtime);if(n){gi({...t,hints:n});return}e.sessionReused||vi(t)}catch{}}function Ii(e,t){try{vi($(e,t))}catch{}}function Li(e){let t=e.lease;if(!g(t))throw Error(`Invalid lease response from daemon`);return{leaseId:h(t,`leaseId`),tenantId:h(t,`tenantId`),runId:h(t,`runId`),backend:h(t,`backend`),leaseProvider:f(t,`leaseProvider`),clientId:f(t,`clientId`),deviceKey:f(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{kr as a,Fr as i,bi as n,oi as r,yi as t};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { H as PlatformSelector } from "./sdk-contracts.js";
|
|
2
|
+
import { t as AgentDeviceClient } from "./client-types.js";
|
|
3
|
+
import { ToolApprovalStatus, ToolSet } from "ai";
|
|
4
|
+
//#region src/ai-sdk/index.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* `'core'` — the curated perceive/act loop (see the `frameworkTier` pinning
|
|
7
|
+
* test in `src/core/command-descriptor/__tests__/parity.test.ts`). `'all'`
|
|
8
|
+
* exposes every MCP-exposed command, same set the MCP server surfaces.
|
|
9
|
+
*/
|
|
10
|
+
type AgentDeviceToolSet = 'core' | 'all';
|
|
11
|
+
type CreateAgentDeviceToolsOptions = {
|
|
12
|
+
/**
|
|
13
|
+
* The agent-device session every tool call targets. Required: pinning one
|
|
14
|
+
* session here is what lets the model call these tools without ever seeing
|
|
15
|
+
* (or being able to typo) a session name — mirroring the "keep the client
|
|
16
|
+
* outside tool execution so calls share one named session" guidance in the
|
|
17
|
+
* AI SDK doc.
|
|
18
|
+
*/
|
|
19
|
+
session: string;
|
|
20
|
+
/**
|
|
21
|
+
* When set, pins every tool call to this platform the same way `session` is
|
|
22
|
+
* pinned, and removes `platform` from the tools' input schemas. Omit it to
|
|
23
|
+
* let each call (and the daemon's own default-device selection) decide.
|
|
24
|
+
*/
|
|
25
|
+
platform?: PlatformSelector;
|
|
26
|
+
/** Which tools to build. Defaults to `'core'`. */
|
|
27
|
+
set?: AgentDeviceToolSet;
|
|
28
|
+
/**
|
|
29
|
+
* Per-command approval policy, keyed by command name (e.g. `install`,
|
|
30
|
+
* `close`). Returned as `toolApproval`, ready to pass straight to
|
|
31
|
+
* `ToolLoopAgent`/`generateText`/`streamText` — see
|
|
32
|
+
* https://ai-sdk.dev/docs/agents/tool-approvals. `tool()`'s own
|
|
33
|
+
* `needsApproval` option is deprecated in favor of this, so this factory
|
|
34
|
+
* never sets it.
|
|
35
|
+
*/
|
|
36
|
+
approval?: Partial<Record<string, ToolApprovalStatus>>;
|
|
37
|
+
};
|
|
38
|
+
type AgentDeviceTools = {
|
|
39
|
+
tools: ToolSet;
|
|
40
|
+
client: AgentDeviceClient;
|
|
41
|
+
toolApproval?: Partial<Record<string, ToolApprovalStatus>>;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Builds an AI SDK tool set from the same command registry the MCP server
|
|
45
|
+
* exposes (`listCommandTools()` / `createCommandToolExecutor()`), so the two
|
|
46
|
+
* integrations stay in lockstep without a hand-maintained tool list. Uses
|
|
47
|
+
* `jsonSchema()` against the registry's JSON Schema directly — no zod layer.
|
|
48
|
+
*
|
|
49
|
+
* `ai` is an optional peer dependency, so it is imported lazily here rather
|
|
50
|
+
* than at module scope: importing `agent-device/ai-sdk` itself never
|
|
51
|
+
* requires `ai` to be installed, only calling this function does.
|
|
52
|
+
*
|
|
53
|
+
* The returned `client` is a plain `agent-device` client for the same
|
|
54
|
+
* session, for the host's own setup/teardown (e.g. `client.apps.open(...)`
|
|
55
|
+
* before the loop, `client.sessions.close()` in a `finally`); the tools
|
|
56
|
+
* themselves execute through the registry's own executor, independent of
|
|
57
|
+
* this instance.
|
|
58
|
+
*/
|
|
59
|
+
declare function createAgentDeviceTools(options: CreateAgentDeviceToolsOptions): Promise<AgentDeviceTools>;
|
|
60
|
+
//#endregion
|
|
61
|
+
export { AgentDeviceToolSet, AgentDeviceTools, CreateAgentDeviceToolsOptions, createAgentDeviceTools };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{y as t}from"./sdk-batch-runner.js";import{n}from"./agent-device-client.js";import{i as r,n as i,r as a}from"./command-tools.js";const o=[`session`,`stateDir`,`mcpOutputFormat`,`includeCost`,`responseLevel`];async function s(s){let{jsonSchema:d,tool:f}=await c(),{session:p,platform:m,set:h=`core`,approval:g}=s,_=n({session:p,...m?{lockPlatform:m}:{}}),v=i(),y=new Set(o);m&&y.add(`platform`);let b={};for(let n of a())h===`core`&&t(n.name)!==`core`||(b[n.name]=f({description:n.description,inputSchema:d(l(n.inputSchema,y)),...n.outputSchema?{outputSchema:d(n.outputSchema)}:{},execute:async t=>{let i={...u(t,y),session:p,...m?{platform:m}:{}},a=await v.execute(n.name,i);if(a.isError){let t=a.structuredContent;throw new e(t.code,r(t),t.details)}return a.structuredContent??{}}}));return{tools:b,client:_,...g?{toolApproval:g}:{}}}async function c(){try{return await import(`ai`)}catch(t){throw new e(`MISSING_PEER_DEPENDENCY`,"createAgentDeviceTools() requires the optional peer dependency 'ai'. Install it with `pnpm add ai` (or npm/yarn equivalent).",void 0,t)}}function l(e,t){if(!e.properties)return e;let n=e.required?.filter(e=>!t.has(e));return{...e,properties:u(e.properties,t),...n?{required:n}:{}}}function u(e,t){let n={};for(let[r,i]of Object.entries(e))t.has(r)||(n[r]=i);return n}export{s as createAgentDeviceTools};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as createAndroidPortReverseManager, i as AndroidPortReverseEndpoint, n as AndroidAdbExecutorOptions, r as AndroidAdbProvider, t as AndroidAdbExecutor } from "./sdk-android-adb.js";
|
|
2
1
|
import { t as AppsFilter } from "./app-inventory.js";
|
|
2
|
+
import { a as createAndroidPortReverseManager, i as AndroidPortReverseEndpoint, n as AndroidAdbExecutorOptions, r as AndroidAdbProvider, t as AndroidAdbExecutor } from "./sdk-android-adb.js";
|
|
3
3
|
import { a as readAndroidClipboardWithAdb, i as getAndroidKeyboardStatusWithAdb, n as AndroidKeyboardState, o as writeAndroidClipboardWithAdb, r as dismissAndroidKeyboardWithAdb, t as AndroidKeyboardDismissResult } from "./device-input-state.js";
|
|
4
4
|
//#region packages/contracts/src/app-state-runtime.d.ts
|
|
5
5
|
/** Neutral foreground identity returned by a selected platform/provider runtime. */
|