agent-device 0.14.9 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +7 -4
  2. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.14.9.apk → agent-device-android-snapshot-helper-0.15.0.apk} +0 -0
  3. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.15.0.apk.sha256 +1 -0
  4. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.14.9.manifest.json → agent-device-android-snapshot-helper-0.15.0.manifest.json} +6 -6
  5. package/dist/src/1769.js +7 -0
  6. package/dist/src/2151.js +429 -0
  7. package/dist/src/221.js +4 -4
  8. package/dist/src/2842.js +1 -0
  9. package/dist/src/3572.js +1 -0
  10. package/dist/src/4057.js +1 -1
  11. package/dist/src/840.js +2 -0
  12. package/dist/src/9542.js +2 -2
  13. package/dist/src/9639.js +2 -2
  14. package/dist/src/android-adb.d.ts +38 -9
  15. package/dist/src/android-adb.js +1 -1
  16. package/dist/src/android-snapshot-helper.d.ts +23 -0
  17. package/dist/src/cli.js +60 -57
  18. package/dist/src/contracts.d.ts +1 -0
  19. package/dist/src/finders.d.ts +1 -0
  20. package/dist/src/index.d.ts +19 -22
  21. package/dist/src/internal/companion-tunnel.js +1 -1
  22. package/dist/src/internal/daemon.js +51 -23
  23. package/dist/src/remote-config.d.ts +17 -14
  24. package/dist/src/selectors.d.ts +2 -0
  25. package/dist/src/server.js +2 -20
  26. package/ios-runner/AgentDeviceRunner/AgentDeviceRunner.xcodeproj/xcshareddata/xcschemes/AgentDeviceRunner.xcscheme +7 -1
  27. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +128 -47
  28. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +734 -10
  29. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +93 -7
  30. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +5 -0
  31. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +9 -0
  32. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +1 -0
  33. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +1 -2
  34. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests.xctestplan +26 -0
  35. package/package.json +25 -11
  36. package/server.json +3 -3
  37. package/skills/agent-device/SKILL.md +2 -7
  38. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.14.9.apk.sha256 +0 -1
  39. package/dist/src/180.js +0 -1
  40. package/dist/src/6108.js +0 -26
  41. package/dist/src/6642.js +0 -1
  42. package/dist/src/7462.js +0 -1
  43. package/dist/src/8809.js +0 -8
  44. package/dist/src/command-schema.js +0 -382
@@ -72,6 +72,21 @@ extension RunnerTests {
72
72
 
73
73
  // MARK: - Target Activation
74
74
 
75
+ func ensureRunnerHostAppActive(reason: String) {
76
+ NSLog(
77
+ "AGENT_DEVICE_RUNNER_HOST_ACTIVATE state=%d reason=%@",
78
+ app.state.rawValue,
79
+ reason
80
+ )
81
+ if app.state == .unknown || app.state == .notRunning {
82
+ app.launch()
83
+ } else if app.state != .runningForeground {
84
+ app.activate()
85
+ }
86
+ currentApp = app
87
+ currentBundleId = nil
88
+ }
89
+
75
90
  func targetNeedsActivation(_ target: XCUIApplication) -> Bool {
76
91
  let state = target.state
77
92
  #if os(macOS)
@@ -88,6 +103,24 @@ extension RunnerTests {
88
103
  return false
89
104
  }
90
105
 
106
+ func canUseFastForegroundAppGuard(
107
+ activeApp: XCUIApplication,
108
+ requestedBundleId: String?,
109
+ command: CommandType
110
+ ) -> Bool {
111
+ guard let requestedBundleId, currentBundleId == requestedBundleId, currentApp != nil else {
112
+ return false
113
+ }
114
+ guard activeApp.state == .runningForeground else { return false }
115
+ NSLog(
116
+ "AGENT_DEVICE_RUNNER_FAST_APP_GUARD command=%@ bundle=%@ state=%d",
117
+ String(describing: command),
118
+ requestedBundleId,
119
+ activeApp.state.rawValue
120
+ )
121
+ return true
122
+ }
123
+
91
124
  func activateTarget(bundleId: String, reason: String) -> XCUIApplication {
92
125
  let target = XCUIApplication(bundleIdentifier: bundleId)
93
126
  NSLog(
@@ -109,18 +142,53 @@ extension RunnerTests {
109
142
  operation: () -> Void
110
143
  ) {
111
144
  let setter = NSSelectorFromString("setWaitForIdleTimeout:")
112
- guard target.responds(to: setter) else {
113
- operation()
114
- return
145
+ let supportsWaitForIdleTimeout = target.responds(to: setter)
146
+ let previous = supportsWaitForIdleTimeout
147
+ ? (target.value(forKey: "waitForIdleTimeout") as? NSNumber)
148
+ : nil
149
+ if supportsWaitForIdleTimeout {
150
+ target.setValue(resolveScrollInteractionIdleTimeout(), forKey: "waitForIdleTimeout")
115
151
  }
116
- let previous = target.value(forKey: "waitForIdleTimeout") as? NSNumber
117
- target.setValue(resolveScrollInteractionIdleTimeout(), forKey: "waitForIdleTimeout")
118
152
  defer {
119
153
  if let previous {
120
154
  target.setValue(previous.doubleValue, forKey: "waitForIdleTimeout")
121
155
  }
122
156
  }
123
- operation()
157
+ performWithQuiescenceSkippedIfSupported(target, operation: operation)
158
+ }
159
+
160
+ // Some apps never report post-gesture quiescence, even after XCTest has synthesized the event.
161
+ private func performWithQuiescenceSkippedIfSupported(
162
+ _ target: XCUIApplication,
163
+ operation: () -> Void
164
+ ) {
165
+ let selector = NSSelectorFromString("_performWithInteractionOptions:block:")
166
+ guard target.responds(to: selector) else {
167
+ operation()
168
+ return
169
+ }
170
+ typealias PerformWithInteractionOptions = @convention(c) (
171
+ NSObject,
172
+ Selector,
173
+ UInt,
174
+ @convention(block) () -> Void
175
+ ) -> Void
176
+ let implementation = target.method(for: selector)
177
+ let performWithOptions = unsafeBitCast(
178
+ implementation,
179
+ to: PerformWithInteractionOptions.self
180
+ )
181
+ let skipPreEventQuiescence = UInt(1)
182
+ let skipPostEventQuiescence = UInt(2)
183
+ withoutActuallyEscaping(operation) { escapableOperation in
184
+ let block: @convention(block) () -> Void = escapableOperation
185
+ performWithOptions(
186
+ target,
187
+ selector,
188
+ skipPreEventQuiescence | skipPostEventQuiescence,
189
+ block
190
+ )
191
+ }
124
192
  }
125
193
 
126
194
  private func resolveScrollInteractionIdleTimeout() -> TimeInterval {
@@ -202,7 +270,7 @@ extension RunnerTests {
202
270
 
203
271
  func isRunnerLifecycleCommand(_ command: CommandType) -> Bool {
204
272
  switch command {
205
- case .shutdown, .recordStop, .screenshot:
273
+ case .shutdown, .recordStop, .screenshot, .uptime:
206
274
  return true
207
275
  default:
208
276
  return false
@@ -224,6 +292,24 @@ extension RunnerTests {
224
292
 
225
293
  func sleepFor(_ delay: TimeInterval) {
226
294
  guard delay > 0 else { return }
295
+ // Keep XCTest/UI sources moving during command-local pauses such as delayed typing.
296
+ if Thread.isMainThread {
297
+ let deadline = Date().addingTimeInterval(delay)
298
+ while Date() < deadline {
299
+ let slice = min(max(deadline.timeIntervalSinceNow, 0), 0.02)
300
+ if slice <= 0 {
301
+ break
302
+ }
303
+ let handledSource = RunLoop.current.run(
304
+ mode: .default,
305
+ before: Date().addingTimeInterval(slice)
306
+ )
307
+ if !handledSource {
308
+ usleep(useconds_t(slice * 1_000_000))
309
+ }
310
+ }
311
+ return
312
+ }
227
313
  usleep(useconds_t(delay * 1_000_000))
228
314
  }
229
315
  }
@@ -12,6 +12,7 @@ enum CommandType: String, Codable {
12
12
  case type
13
13
  case swipe
14
14
  case findText
15
+ case querySelector
15
16
  case readText
16
17
  case snapshot
17
18
  case screenshot
@@ -34,7 +35,10 @@ struct Command: Codable {
34
35
  let command: CommandType
35
36
  let appBundleId: String?
36
37
  let text: String?
38
+ let selectorKey: String?
39
+ let selectorValue: String?
37
40
  let delayMs: Int?
41
+ let textEntryMode: String?
38
42
  let clearFirst: Bool?
39
43
  let action: String?
40
44
  let x: Double?
@@ -165,6 +169,7 @@ struct SnapshotNode: Codable {
165
169
  let rect: SnapshotRect
166
170
  let enabled: Bool
167
171
  let focused: Bool?
172
+ let selected: Bool?
168
173
  let hittable: Bool
169
174
  let depth: Int
170
175
  let parentIndex: Int?
@@ -29,6 +29,7 @@ extension RunnerTests {
29
29
  let valueText: String?
30
30
  let hittable: Bool
31
31
  let focused: Bool
32
+ let selected: Bool
32
33
  let visible: Bool
33
34
  }
34
35
 
@@ -343,6 +344,7 @@ extension RunnerTests {
343
344
  valueText: valueText,
344
345
  hittable: computedSnapshotHittable(snapshot, viewport: context.viewport, laterNodes: laterNodes),
345
346
  focused: snapshotHasFocus(snapshot),
347
+ selected: snapshotIsSelected(snapshot),
346
348
  visible: isVisibleInViewport(snapshot.frame, context.viewport)
347
349
  )
348
350
  }
@@ -363,6 +365,7 @@ extension RunnerTests {
363
365
  rect: snapshotRect(from: snapshot.frame),
364
366
  enabled: snapshot.isEnabled,
365
367
  focused: evaluation.focused ? true : nil,
368
+ selected: evaluation.selected ? true : nil,
366
369
  hittable: evaluation.hittable,
367
370
  depth: depth,
368
371
  parentIndex: parentIndex,
@@ -529,6 +532,7 @@ extension RunnerTests {
529
532
  rect: node.rect,
530
533
  enabled: node.enabled,
531
534
  focused: node.focused,
535
+ selected: node.selected,
532
536
  hittable: node.hittable,
533
537
  depth: depth,
534
538
  parentIndex: parentIndex,
@@ -580,6 +584,7 @@ extension RunnerTests {
580
584
  rect: snapshotRect(from: frame),
581
585
  enabled: element.isEnabled,
582
586
  focused: elementHasFocus(element) ? true : nil,
587
+ selected: element.isSelected ? true : nil,
583
588
  hittable: element.isHittable,
584
589
  depth: 0,
585
590
  parentIndex: nil,
@@ -607,6 +612,10 @@ extension RunnerTests {
607
612
  return focused
608
613
  }
609
614
 
615
+ private func snapshotIsSelected(_ snapshot: XCUIElementSnapshot) -> Bool {
616
+ return snapshot.isSelected
617
+ }
618
+
610
619
  private func shouldExpandCollapsedTabContainer(_ snapshot: XCUIElementSnapshot) -> Bool {
611
620
  let frame = snapshot.frame
612
621
  if frame.isNull || frame.isEmpty { return false }
@@ -187,6 +187,7 @@ extension RunnerTests {
187
187
  rect: snapshotRect(from: element.frame),
188
188
  enabled: element.isEnabled,
189
189
  focused: elementHasFocus(element) ? true : nil,
190
+ selected: element.isSelected ? true : nil,
190
191
  hittable: hittableOverride ?? element.isHittable,
191
192
  depth: depth,
192
193
  parentIndex: nil,
@@ -90,8 +90,7 @@ final class RunnerTests: XCTestCase {
90
90
  @MainActor
91
91
  func testCommand() throws {
92
92
  doneExpectation = expectation(description: "agent-device command handled")
93
- app.launch()
94
- currentApp = app
93
+ NSLog("AGENT_DEVICE_RUNNER_HEADLESS_STARTUP=1")
95
94
  let queue = DispatchQueue(label: "agent-device.runner")
96
95
  let desiredPort = RunnerEnv.resolvePort()
97
96
  NSLog("AGENT_DEVICE_RUNNER_DESIRED_PORT=%d", desiredPort)
@@ -0,0 +1,26 @@
1
+ {
2
+ "configurations" : [
3
+ {
4
+ "id" : "916C7049-FE79-4C78-B55F-79242F92CB19",
5
+ "name" : "Configuration 1",
6
+ "options" : {
7
+
8
+ }
9
+ }
10
+ ],
11
+ "defaultOptions" : {
12
+ "preferredScreenCaptureFormat" : "screenshots",
13
+ "systemAttachmentLifetime" : "keepNever",
14
+ "userAttachmentLifetime" : "keepNever"
15
+ },
16
+ "testTargets" : [
17
+ {
18
+ "target" : {
19
+ "containerPath" : "container:AgentDeviceRunner.xcodeproj",
20
+ "identifier" : "20EA2EDC2F2CFC7C001CF0EF",
21
+ "name" : "AgentDeviceRunnerUITests"
22
+ }
23
+ }
24
+ ],
25
+ "version" : 1
26
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-device",
3
- "version": "0.14.9",
3
+ "version": "0.15.0",
4
4
  "description": "Agent-native CLI for AI mobile testing and app automation across iOS, Android, tvOS, Android TV, macOS, and Linux.",
5
5
  "mcpName": "io.github.callstackincubator/agent-device",
6
6
  "license": "MIT",
@@ -14,7 +14,7 @@
14
14
  "url": "https://github.com/callstackincubator/agent-device/issues"
15
15
  },
16
16
  "type": "module",
17
- "packageManager": "pnpm@10.33.2",
17
+ "packageManager": "pnpm@11.1.2",
18
18
  "main": "dist/src/index.js",
19
19
  "types": "dist/src/index.d.ts",
20
20
  "exports": {
@@ -76,11 +76,17 @@
76
76
  "scripts": {
77
77
  "build": "rslib build",
78
78
  "clean:daemon": "rm -f ~/.agent-device/daemon.json && rm -f ~/.agent-device/daemon.lock",
79
+ "clean:xcuitest": "node scripts/clean-xcuitest-derived.mjs",
80
+ "clean:xcuitest:ios": "node scripts/clean-xcuitest-derived.mjs ios",
81
+ "clean:xcuitest:macos": "node scripts/clean-xcuitest-derived.mjs macos",
82
+ "clean:xcuitest:tvos": "node scripts/clean-xcuitest-derived.mjs tvos",
79
83
  "build:node": "pnpm build && pnpm clean:daemon",
80
84
  "build:xcuitest": "pnpm build:xcuitest:ios && pnpm build:xcuitest:macos",
81
- "build:xcuitest:ios": "AGENT_DEVICE_XCUITEST_PLATFORM=ios AGENT_DEVICE_IOS_CLEAN_DERIVED=1 sh ./scripts/build-xcuitest-apple.sh",
85
+ "build:xcuitest:ios": "AGENT_DEVICE_XCUITEST_PLATFORM=ios sh ./scripts/build-xcuitest-apple.sh",
86
+ "build:xcuitest:ios:clean": "pnpm clean:xcuitest:ios && pnpm build:xcuitest:ios",
82
87
  "build:xcuitest:macos": "AGENT_DEVICE_XCUITEST_PLATFORM=macos sh ./scripts/build-xcuitest-apple.sh",
83
- "build:xcuitest:tvos": "AGENT_DEVICE_XCUITEST_PLATFORM=tvos AGENT_DEVICE_IOS_CLEAN_DERIVED=1 sh ./scripts/build-xcuitest-apple.sh",
88
+ "build:xcuitest:tvos": "AGENT_DEVICE_XCUITEST_PLATFORM=tvos sh ./scripts/build-xcuitest-apple.sh",
89
+ "build:xcuitest:tvos:clean": "pnpm clean:xcuitest:tvos && pnpm build:xcuitest:tvos",
84
90
  "build:android-snapshot-helper": "sh ./scripts/build-android-snapshot-helper.sh $(node -p \"require('./package.json').version\") .tmp/android-snapshot-helper",
85
91
  "package:android-snapshot-helper": "sh ./scripts/package-android-snapshot-helper.sh $(node -p \"require('./package.json').version\") v$(node -p \"require('./package.json').version\") .tmp/android-snapshot-helper",
86
92
  "package:android-snapshot-helper:npm": "rm -rf android-snapshot-helper/dist && sh ./scripts/package-android-snapshot-helper.sh $(node -p \"require('./package.json').version\") v$(node -p \"require('./package.json').version\") android-snapshot-helper/dist",
@@ -90,7 +96,7 @@
90
96
  "lint": "oxlint . --deny-warnings",
91
97
  "format": "oxfmt --write src test skills package.json tsconfig.json tsconfig.lib.json rslib.config.ts vitest.config.ts .github/actions/setup-node-pnpm/action.yml .oxlintrc.json .oxfmtrc.json '!test/skillgym/.skillgym-results/**'",
92
98
  "fallow": "fallow --summary",
93
- "fallow:baseline": "(fallow dead-code --save-baseline fallow-baselines/dead-code.json --summary || true) && (fallow dupes --save-baseline fallow-baselines/dupes.json --summary || true) && (fallow health --save-baseline fallow-baselines/health.json --summary || true)",
99
+ "fallow:baseline": "(fallow dead-code --save-baseline fallow-baselines/dead-code.json --summary || true) && (fallow health --save-baseline fallow-baselines/health.json --summary || true)",
94
100
  "check:fallow": "fallow audit",
95
101
  "check:quick": "pnpm lint && pnpm typecheck",
96
102
  "sync:mcp-metadata": "node scripts/sync-mcp-metadata.mjs",
@@ -105,11 +111,16 @@
105
111
  "test-app:ios": "pnpm --dir examples/test-app ios",
106
112
  "test-app:android": "pnpm --dir examples/test-app android",
107
113
  "test-app:typecheck": "pnpm --dir examples/test-app typecheck",
108
- "test": "vitest run",
109
- "test:unit": "vitest run",
114
+ "test": "vitest run --project unit",
115
+ "test:unit": "vitest run --project unit",
116
+ "test:coverage": "vitest run --coverage",
117
+ "test:integration:provider": "vitest run --project provider-integration",
118
+ "test:integration:progress": "node scripts/integration-progress.mjs",
119
+ "test:integration:progress:check": "node scripts/integration-progress.mjs --check",
110
120
  "test:skillgym": "pnpm build && skillgym run ./test/skillgym/suites/agent-device-smoke-suite.ts --config ./test/skillgym/skillgym.config.ts",
111
121
  "test:smoke": "node --test test/integration/smoke-*.test.ts",
112
- "test:integration": "node --test test/integration/*.test.ts",
122
+ "test:integration:node": "node --test test/integration/*.test.ts",
123
+ "test:integration": "pnpm test:integration:node && pnpm test:integration:provider",
113
124
  "test:replay:ios": "node --experimental-strip-types src/bin.ts test test/integration/replays/ios/simulator",
114
125
  "test:replay:ios-device": "node --experimental-strip-types src/bin.ts test test/integration/replays/ios/device",
115
126
  "test:replay:android": "node --experimental-strip-types src/bin.ts test test/integration/replays/android",
@@ -183,18 +194,21 @@
183
194
  ],
184
195
  "dependencies": {
185
196
  "fast-xml-parser": "^5.7.2",
186
- "pngjs": "^7.0.0"
197
+ "pngjs": "^7.0.0",
198
+ "yaml": "^2.9.0"
187
199
  },
188
200
  "devDependencies": {
189
- "vitest": "^4.1.2",
201
+ "@microsoft/api-extractor": "^7.58.7",
190
202
  "@rslib/core": "0.20.1",
191
203
  "@types/node": "^22.0.0",
192
204
  "@types/pngjs": "^6.0.5",
205
+ "@vitest/coverage-v8": "4.1.2",
193
206
  "fallow": "^2.52.0",
194
207
  "oxfmt": "^0.42.0",
195
208
  "oxlint": "^1.57.0",
196
209
  "skillgym": "^0.8.0",
197
210
  "typescript": "^6.0.2",
198
- "vite": "^8.0.10"
211
+ "vite": "^8.0.10",
212
+ "vitest": "^4.1.2"
199
213
  }
200
214
  }
package/server.json CHANGED
@@ -2,17 +2,17 @@
2
2
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
3
  "name": "io.github.callstackincubator/agent-device",
4
4
  "title": "agent-device",
5
- "description": "Discovery router for the agent-device CLI with status, install, help, prompts, and resources.",
5
+ "description": "Let AI agents inspect, control, and debug real iOS, Android, desktop, and TV apps",
6
6
  "repository": {
7
7
  "url": "https://github.com/callstackincubator/agent-device",
8
8
  "source": "github"
9
9
  },
10
- "version": "0.14.9",
10
+ "version": "0.15.0",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "identifier": "agent-device",
15
- "version": "0.14.9",
15
+ "version": "0.15.0",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  }
@@ -11,13 +11,7 @@ Router only. Private setup before using this skill:
11
11
  agent-device --version
12
12
  ```
13
13
 
14
- If that fails but the user installed `agent-device` globally, try the user's login shell before using `npx`:
15
-
16
- ```bash
17
- zsh -lic 'command -v agent-device'
18
- ```
19
-
20
- If it prints a path, run that absolute path instead of `agent-device`. For non-zsh shells, use the equivalent login-shell command.
14
+ If that fails but the user may have installed `agent-device` globally, check the user's configured login/interactive shell and environment before using `npx`. Resolve the command the same way the user would from a normal terminal session, then run the absolute binary path if found. This may require inspecting shell startup behavior or package-manager/global bin locations; do not assume the Codex process `PATH` is the user's `PATH`.
21
15
 
22
16
  Require `agent-device >= 0.14.0`; older CLIs lack these help topics. If older, stop and tell the user to upgrade the trusted install or approve an exact-version npm command. Do not run `npm install -g agent-device@latest` or `npx -y agent-device@latest` autonomously, and do not include version/upgrade commands in final plans.
23
17
 
@@ -31,6 +25,7 @@ Escalate only when relevant:
31
25
 
32
26
  ```bash
33
27
  agent-device help debugging
28
+ agent-device help react-native
34
29
  agent-device help react-devtools
35
30
  agent-device help remote
36
31
  agent-device help macos
@@ -1 +0,0 @@
1
- 6dfb064793721b49e6111162a428f312bc9365dfc06e05adb648c434105fdf4e agent-device-android-snapshot-helper-0.14.9.apk
package/dist/src/180.js DELETED
@@ -1 +0,0 @@
1
- import e from"node:path";import t from"node:crypto";import n from"node:fs";import{resolveUserPath as a,expandUserHomePath as i}from"./3267.js";import{findProjectRoot as r}from"./9671.js";function o(t){let n,r=(n=(t??"").trim())?a(n):e.join(i("~"),".agent-device");return{baseDir:r,infoPath:e.join(r,"daemon.json"),lockPath:e.join(r,"daemon.lock"),logPath:e.join(r,"daemon.log"),sessionsDir:e.join(r,"sessions")}}function s(e){let t=(e??"").trim().toLowerCase();return"http"===t?"http":"dual"===t?"dual":"socket"}function l(e){let t=(e??"").trim().toLowerCase();return"auto"===t?"auto":"socket"===t?"socket":"http"===t?"http":"auto"}function d(e){return"tenant"===(e??"").trim().toLowerCase()?"tenant":"none"}function u(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}let p=/(?:^|[^\w$.])(?:import|export)\s+(?:type\s+)?(?:[^'"`]*?\s+from\s+)?['"]([^'"]+)['"]/gm,c=/import\(\s*['"]([^'"]+)['"]\s*\)/gm,m=[".ts",".tsx",".js",".jsx",".mjs",".cjs"];function f(){let e=process.argv[1];return e?h(e):"unknown"}function h(a,i=r()){try{let r=e.resolve(i),o=[e.resolve(a)],s=new Set,l=[];for(;o.length>0;){let t=o.pop();if(!t||s.has(t))continue;s.add(t);let a=n.statSync(t);if(!a.isFile())continue;let i=e.relative(r,t)||t;l.push(`${i}:${a.size}:${Math.trunc(a.mtimeMs)}`);let d=n.readFileSync(t,"utf8");for(let n of function(e){let t=new Set;return g(e,p,t),g(e,c,t),[...t]}(d)){let a=function(t,n){let a=e.resolve(e.dirname(t),n),i=I(a);if(i)return i;for(let e of m){let t=I(`${a}${e}`);if(t)return t}for(let t of m){let n=I(e.join(a,`index${t}`));if(n)return n}return null}(t,n);a&&o.push(a)}}let d=l.sort().join("|"),u=t.createHash("sha1").update(d).digest("hex");return`graph:${l.length}:${u}`}catch{return"unknown"}}function g(e,t,n){t.lastIndex=0;let a=null;for(;null!==(a=t.exec(e));){let e=a[1]?.trim();e?.startsWith(".")&&n.add(e)}}function I(e){try{return n.statSync(e).isFile()?e:null}catch{return null}}function v(e){return e?{message:e}:{}}function S(e,t){return t?{...e,message:t}:e}function b(e){return"string"==typeof e?.message&&e.message.length>0?e.message:null}function k(e){let t=e.appId??e.bundleId??e.packageName;return{session:e.session,appId:t,appBundleId:e.bundleId,package:e.packageName}}function N(e,t,n){return{deviceId:t,deviceName:n,..."android"===e?{serial:t}:"ios"===e?{udid:t}:{}}}function $(e,t={}){let n=t.includeAndroidSerial??!0;return{platform:e.platform,target:e.target,device:e.name,id:e.id,..."ios"===e.platform?{device_udid:e.ios?.udid??e.id,ios_simulator_device_set:e.ios?.simulatorSetPath??null}:{},..."android"===e.platform&&n?{serial:e.android?.serial??e.id}:{}}}function _(e){return{name:e.name,...$(e.device,{includeAndroidSerial:!1}),createdAt:e.createdAt}}function z(e){return{platform:e.platform,id:e.id,name:e.name,kind:e.kind,target:e.target,..."boolean"==typeof e.booted?{booted:e.booted}:{}}}function w(e){let t=e.created?"Created":"Reused",n=e.booted?" (booted)":"";return S({udid:e.udid,device:e.device,runtime:e.runtime,ios_simulator_device_set:e.iosSimulatorDeviceSet??null,created:e.created,booted:e.booted},`${t}: ${e.device} ${e.udid}${n}`)}function P(e){return e.bundleId??e.package??e.app}function y(e){return S({app:e.app,appPath:e.appPath,platform:e.platform,...e.appId?{appId:e.appId}:{},...e.bundleId?{bundleId:e.bundleId}:{},...e.package?{package:e.package}:{}},`Installed: ${P(e)}`)}function C(e){return e.appName??e.bundleId??e.packageName??e.launchTarget}function x(e){return S({launchTarget:e.launchTarget,...e.appName?{appName:e.appName}:{},...e.appId?{appId:e.appId}:{},...e.bundleId?{bundleId:e.bundleId}:{},...e.packageName?{package:e.packageName}:{},...e.installablePath?{installablePath:e.installablePath}:{},...e.archivePath?{archivePath:e.archivePath}:{},...e.materializationId?{materializationId:e.materializationId}:{},...e.materializationExpiresAt?{materializationExpiresAt:e.materializationExpiresAt}:{}},`Installed: ${C(e)}`)}function j(e){let t=e.appName??e.appBundleId??e.session;return S({session:e.session,...e.appName?{appName:e.appName}:{},...e.appBundleId?{appBundleId:e.appBundleId}:{},...e.startup?{startup:e.startup}:{},...e.runtime?{runtime:e.runtime}:{},...e.device?$(e.device):{}},t?`Opened: ${t}`:"Opened")}function A(e){return{session:e.session,...e.shutdown?{shutdown:e.shutdown}:{},...v(e.session?`Closed: ${e.session}`:"Closed")}}function D(e){return{nodes:e.nodes,truncated:e.truncated,...e.appName?{appName:e.appName}:{},...e.appBundleId?{appBundleId:e.appBundleId}:{},...e.visibility?{visibility:e.visibility}:{},...e.androidSnapshot?{androidSnapshot:e.androidSnapshot}:{},...e.warnings&&e.warnings.length>0?{warnings:e.warnings}:{}}}export{k as buildAppIdentifiers,N as buildDeviceIdentifiers,h as computeDaemonCodeSignature,u as normalizeTenantId,b as readCommandMessage,f as resolveDaemonCodeSignature,o as resolveDaemonPaths,s as resolveDaemonServerMode,l as resolveDaemonTransportPreference,P as resolveDeployResultTarget,C as resolveInstallFromSourceResultTarget,d as resolveSessionIsolationMode,A as serializeCloseResult,y as serializeDeployResult,z as serializeDevice,w as serializeEnsureSimulatorResult,x as serializeInstallFromSourceResult,j as serializeOpenResult,_ as serializeSessionListEntry,D as serializeSnapshotResult,v as successText,S as withSuccessText};