stim 1.20.2 → 1.22.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 (231) hide show
  1. package/README.md +141 -8
  2. package/dist/acquire-artifact-Co2k4f7O.mjs +171 -0
  3. package/dist/act-DsuqEkiM.mjs +2801 -0
  4. package/dist/activity-CMLmzp7o.mjs +1397 -0
  5. package/dist/{agent-device-usage-output-Dzgv6lgR.mjs → agent-device-usage-output-DUFaTMdd.mjs} +23 -67
  6. package/dist/{android-DCKZrNvV.mjs → android-ByRMUoiJ.mjs} +157 -93
  7. package/dist/{android-Mz_Inn3w.mjs → android-C7sVmyI9.mjs} +299 -116
  8. package/dist/{android-Dlzxshgp.mjs → android-DGkNqa_c.mjs} +5 -5
  9. package/dist/{android-HqP1_vB_.mjs → android-DR5lZ2Az.mjs} +2 -2
  10. package/dist/android-cas-compiler.mjs +2 -2
  11. package/dist/{android-cas-Bl-cLJBk.mjs → android-cas-ngferVq2.mjs} +7 -6
  12. package/dist/android-project-BCAAmMwz.mjs +12 -0
  13. package/dist/android-project-DVWyCbWU.d.mts +391 -0
  14. package/dist/api.d.mts +810 -64
  15. package/dist/api.mjs +782 -1
  16. package/dist/{artifact-HSwkIWEQ.mjs → artifact-8EY8SAPw.mjs} +240 -213
  17. package/dist/{artifact-D3czlUvT.mjs → artifact-DJPy518Y.mjs} +203 -164
  18. package/dist/artifact-platform-CXcmX_j3.mjs +27 -0
  19. package/dist/{browser-web-CA-F1GQo.mjs → browser-web-Bcv99PBM.mjs} +194 -64
  20. package/dist/budget-Cvwn54qV.mjs +9285 -0
  21. package/dist/{build-DYDbfkk5.mjs → build-CabC3G23.mjs} +153 -98
  22. package/dist/build-cache-Dv7RN200.mjs +602 -0
  23. package/dist/build-plan-DUC8Ka9y.mjs +248 -0
  24. package/dist/{cache-manifest-XH-fvDUj.mjs → cache-manifest-DSeQjt-Q.mjs} +2 -2
  25. package/dist/cache-manifest.mjs +1 -1
  26. package/dist/{ccache-zdKiYQ3E.mjs → ccache-Btwc36-I.mjs} +10 -9
  27. package/dist/{cdp-Dq_ypAlJ.mjs → cdp-3fwICjzi.mjs} +18 -5
  28. package/dist/{chrome-BnzZMqsR.mjs → chrome-Bbw689-6.mjs} +7 -4
  29. package/dist/{cli-CLP3diBm.mjs → cli-CHZa9Lvk.mjs} +20 -20
  30. package/dist/cli.mjs +1 -1
  31. package/dist/client-OyRoEuSr.mjs +1577 -0
  32. package/dist/collector-run.d.mts +4 -40
  33. package/dist/collector-run.mjs +9 -8
  34. package/dist/{command-output-BTy8hZ0F.mjs → command-output-gwpm28fu.mjs} +1 -1
  35. package/dist/config-DlrsduwG.mjs +955 -0
  36. package/dist/{created-devices-Dzd5C2LF.mjs → created-devices-x9rN6bhs.mjs} +14 -4
  37. package/dist/{dependency-state-DG0p31-y.mjs → dependency-state-1I9KZT1Y.mjs} +20 -5
  38. package/dist/{detached-entry-B9C_zeQC.mjs → detached-entry-BwNEtIrP.mjs} +1 -1
  39. package/dist/{dev-client-DAWVIGBu.mjs → dev-client-BSDR5h3F.mjs} +2 -2
  40. package/dist/{device-BECOiufl.mjs → device-B-L3Fbxy.mjs} +91 -34
  41. package/dist/device-DklWZLqb.mjs +1068 -0
  42. package/dist/{device-capacity-CBUAcRyQ.mjs → device-capacity-DK5_EwRS.mjs} +42 -13
  43. package/dist/device-host-worker.mjs +76 -79
  44. package/dist/{device-ios-COSi6oS1.mjs → device-ios-DoB6KFCO.mjs} +77 -51
  45. package/dist/{device-lease-run-Cw2M4z51.mjs → device-lease-run-xJPQ_QQG.mjs} +14 -26
  46. package/dist/{device-pool-Bf-pOhSw.mjs → device-pool-BMkdsefq.mjs} +5 -5
  47. package/dist/{doctor-kfMBnUw6.mjs → doctor-Bo7BXLux.mjs} +271 -320
  48. package/dist/{doctor-CB8oZKCk.mjs → doctor-D5_EzwfA.mjs} +186 -91
  49. package/dist/doctor-fingerprint-DZLoYFVb.mjs +16 -0
  50. package/dist/doctor-fingerprint.mjs +19 -0
  51. package/dist/doctor-thjWAV0z.mjs +2 -0
  52. package/dist/{doctor-watchman-BRyV2adA.mjs → doctor-watchman-N2wDotwQ.mjs} +40 -21
  53. package/dist/{eas-build-JyfqyHfC.mjs → eas-build-CwknaQYj.mjs} +53 -20
  54. package/dist/{build-plan-B7SZsc2N.mjs → eas-fallback-CSgAulr5.mjs} +41 -214
  55. package/dist/{watchman-CPQFZLXY.mjs → eas-session-ledger-DlY_serQ.mjs} +230 -11
  56. package/dist/{error-diagnostics-BR677IDM.mjs → error-diagnostics-DBWO2rxE.mjs} +172 -82
  57. package/dist/exec-DEoAhcze.mjs +858 -0
  58. package/dist/exec-DnYc4HGH.d.mts +78 -0
  59. package/dist/{gc-qWOMdnER.mjs → gc-CXxN-4SE.mjs} +1091 -1029
  60. package/dist/gc-DnNDQyaP.mjs +3 -0
  61. package/dist/{guide-G9cAbVAc.mjs → guide-Br0LEfKy.mjs} +1165 -297
  62. package/dist/{hosted-android-C3MHGld1.mjs → hosted-android-B-9f-jkd.mjs} +10 -8
  63. package/dist/{hosted-client-ZEKpS9vw.mjs → hosted-client-DZAPrcro.mjs} +34 -19
  64. package/dist/{hosted-ios-l-o3iM9J.mjs → hosted-ios-CsCS21hn.mjs} +1 -1
  65. package/dist/{hosted-logs-EzQM7-3Z.mjs → hosted-logs-FIRx9X2f.mjs} +77 -43
  66. package/dist/{hosted-macos-BACVAVqE.mjs → hosted-macos-_awYSpfv.mjs} +35 -22
  67. package/dist/{hosted-native-A4s1QPXe.mjs → hosted-native-BdzE668-.mjs} +49 -27
  68. package/dist/idle-C4cZ757K.d.mts +24 -0
  69. package/dist/{idle-shutdown-DtxhPTKe.mjs → idle-shutdown-DDg3SdvY.mjs} +11 -10
  70. package/dist/ios-CDvlmUs7.d.mts +24 -0
  71. package/dist/{ios-BwVCF7oA.mjs → ios-Ds1clbIt.mjs} +8 -8
  72. package/dist/{ios-device-D7pi2Sca.mjs → ios-device--h_-8ENa.mjs} +51 -26
  73. package/dist/{ios-device-B5veSDDQ.mjs → ios-device-BXZ0c7Kb.mjs} +1 -1
  74. package/dist/{ios-RkW4pnQf.mjs → ios-hcBpnEGk.mjs} +200 -93
  75. package/dist/{ios-Ce7bc7br.mjs → ios-pm4nL6By.mjs} +160 -108
  76. package/dist/{ios-project-K9hY_Jab.mjs → ios-project-CZhKODF3.mjs} +13 -13
  77. package/dist/ios-signing-BtAffm0A.mjs +489 -0
  78. package/dist/{ios-state-CBLe1xYw.mjs → ios-state-Dtw5K2aI.mjs} +1 -1
  79. package/dist/{ios-nOLJGVdy.mjs → ios-xtlRHaeB.mjs} +1 -1
  80. package/dist/{js-swap-Bb3nsS07.mjs → js-swap-Bwhh4S7V.mjs} +30 -25
  81. package/dist/{launch-C3qJ6Agb.mjs → launch-BjxemNpK.mjs} +85 -543
  82. package/dist/{launch-F4sOqAhB.mjs → launch-CCzXlc8r.mjs} +91 -90
  83. package/dist/logs-BfwwadsZ.mjs +479 -0
  84. package/dist/logs-jTS_lHSo.mjs +248 -0
  85. package/dist/{macos-D7uDvO-z.mjs → macos-DVlSSyUg.mjs} +1 -1
  86. package/dist/macos-NfV2D7dO.mjs +694 -0
  87. package/dist/macos-run.mjs +1 -1
  88. package/dist/maintenance-run.mjs +123 -248
  89. package/dist/{metro-DnCEjCxs.mjs → metro-DiXtA3Ty.mjs} +107 -30
  90. package/dist/metro-gateway-CKZqKqx7.mjs +209 -0
  91. package/dist/{named-ports-4WopRPg-.mjs → named-ports-DkEzOfzO.mjs} +42 -90
  92. package/dist/native-android-CqgnOgsT.mjs +645 -0
  93. package/dist/native-gradle-artifact-inputs-DHFnmrVf.mjs +270 -0
  94. package/dist/native-gradle-inputs-Dnh84Zbd.mjs +211 -0
  95. package/dist/native-inputs-TRTTTRxt.mjs +91 -0
  96. package/dist/native-run-NwUuxbkg.mjs +276 -0
  97. package/dist/{native-runtime-k8dTIrbK.mjs → native-runtime-B7KIafpM.mjs} +11 -9
  98. package/dist/native-source-Y0yLhFyQ.mjs +133 -0
  99. package/dist/{native-xcode-inputs-CykopJdM.mjs → native-xcode-inputs-D_VOfFL7.mjs} +26 -18
  100. package/dist/{native-xcode-ios-Bbf30Gm0.mjs → native-xcode-ios-BYDOHWLN.mjs} +104 -60
  101. package/dist/{ndjson-GOnbyvso.mjs → ndjson-CgE_o3Dl.mjs} +3 -3
  102. package/dist/offload-worker.d.mts +59 -41
  103. package/dist/offload-worker.mjs +478 -115
  104. package/dist/operation-exec-BW0em61G.mjs +171 -0
  105. package/dist/{ownership-DCtw_2IA.mjs → ownership-C5fo5Edb.mjs} +3 -3
  106. package/dist/{page-DRHy329N.mjs → page-DBL2PiUU.mjs} +12 -5
  107. package/dist/paths-BsJMoPP2.mjs +12 -0
  108. package/dist/paths-DQtTgsBf.mjs +42 -0
  109. package/dist/{placement-log-MOfPVgaM.mjs → placement-log-BnGgJRRZ.mjs} +5 -5
  110. package/dist/{plan-placement-V0TdzYXp.mjs → plan-placement-DIsMtN-d.mjs} +15 -11
  111. package/dist/{ports-DdSUicVo.mjs → ports-Cy1RkmuQ.mjs} +3 -3
  112. package/dist/prebuild-D4JoEAEs.mjs +484 -0
  113. package/dist/{project-_phNIJfs.mjs → project-wM_XFTvE.mjs} +65 -37
  114. package/dist/{pull-request-CQ8sPbZa.mjs → pull-request-W1IuLXDt.mjs} +102 -20
  115. package/dist/pull-request-eODyIqZF.d.mts +124 -0
  116. package/dist/pull-requests.d.mts +2 -120
  117. package/dist/pull-requests.mjs +2 -2
  118. package/dist/{react-native-android-CM1XRDwv.mjs → react-native-android-6OZ7MSM7.mjs} +121 -72
  119. package/dist/{gradle-DSrXb6lG.mjs → react-native-build-Dvd8hC21.mjs} +292 -15
  120. package/dist/react-native-doctor-DsoSF1Y9.mjs +234 -0
  121. package/dist/{react-native-ios-Dhq_eiYQ.mjs → react-native-ios-4u1Rn-GR.mjs} +71 -39
  122. package/dist/{recordings-D0d5aQt0.mjs → recordings-CQmfzAh7.mjs} +12 -9
  123. package/dist/registration-BcRgF6Ox.mjs +51 -0
  124. package/dist/{reload-C8JhxjSh.mjs → reload-BzkYabB-.mjs} +94 -47
  125. package/dist/reload-D7AVlb8N.mjs +2 -0
  126. package/dist/{remote-BiR6aYjy.mjs → remote-DjGDmlTZ.mjs} +26 -18
  127. package/dist/result-D2Ykz_iD.mjs +435 -0
  128. package/dist/{run-BtPgpKks.mjs → run-DidHghD1.mjs} +5 -5
  129. package/dist/selection-DSMbWEX2.mjs +620 -0
  130. package/dist/{server-bare-R2m_gsH8.mjs → server-bare-CafzuyFB.mjs} +3 -4
  131. package/dist/{server-command-CTtCkmcQ.mjs → server-command-C6QjeupS.mjs} +14 -7
  132. package/dist/{server-expo-DsguMGUF.mjs → server-expo-CrjB29pq.mjs} +54 -11
  133. package/dist/server-expo-D58c9L0M.mjs +2 -0
  134. package/dist/{settings-B717odTD.mjs → settings-C7O8A6ZI.mjs} +309 -119
  135. package/dist/settings-DpR-1Wnn.mjs +114 -0
  136. package/dist/settings-write-CzD60rOD.mjs +360 -0
  137. package/dist/settings.schema.json +176 -16
  138. package/dist/{simslim-CCr3rE-A.mjs → simslim-BNckWpXi.mjs} +14 -12
  139. package/dist/{slot-launch-DPt0m9Nd.mjs → slot-launch-CbfmNgM6.mjs} +15 -20
  140. package/dist/{spawn-entry-Dcb7sDUz.mjs → spawn-entry-jw19m8Nl.mjs} +0 -1
  141. package/dist/stage-Bps5oius.mjs +200 -0
  142. package/dist/{start-TXeMmmO2.mjs → start-Br-oxqMD.mjs} +1 -1
  143. package/dist/start-EojN4WFz.mjs +1364 -0
  144. package/dist/{state-D1Icyjlu.mjs → state--smjFSTL.mjs} +55 -13
  145. package/dist/{state-CG_OFoaA.mjs → state-08I3hw3_.mjs} +3 -2
  146. package/dist/{stats-BoY5sEPU.mjs → stats-D3GerlFW.mjs} +7 -13
  147. package/dist/stats-report-BzaPrRm6.mjs +16 -0
  148. package/dist/{status-BTA7kKiQ.mjs → status-BRROykC8.mjs} +7 -5
  149. package/dist/status-EvrK72L2.mjs +2 -0
  150. package/dist/{status-WgFbkRzj.mjs → status-WBDajew2.mjs} +554 -452
  151. package/dist/{status-watch-C23ILtf9.mjs → status-watch-Bg_u-pwR.mjs} +222 -25
  152. package/dist/status-worker.d.mts +1 -0
  153. package/dist/status-worker.mjs +19 -0
  154. package/dist/stim-desktop-D5OGpYZM.mjs +112 -0
  155. package/dist/{stop-DR6VoDIk.mjs → stop-DTZ9uTw3.mjs} +2 -2
  156. package/dist/{stop-DPEhunlw.mjs → stop-Dky10AEJ.mjs} +33 -23
  157. package/dist/{stop-BNmBMi1F.mjs → stop-Mv6W9FAk.mjs} +137 -98
  158. package/dist/supervisor-run.d.mts +8 -17
  159. package/dist/supervisor-run.mjs +56 -28
  160. package/dist/{support-CwjbFs9H.mjs → support-CNioewsd.mjs} +14 -14
  161. package/dist/{support-DMTqj3Hm.mjs → support-yUiOjnVY.mjs} +20 -13
  162. package/dist/swiftpm-artifact-inputs-DFcGsXDP.mjs +153 -0
  163. package/dist/swiftpm-macos-BIak-Rxv.mjs +532 -0
  164. package/dist/toolchain-BY8X8HXx.mjs +2 -0
  165. package/dist/toolchain-DpJMHq0n.mjs +876 -0
  166. package/dist/{trigger-CigAYjeL.mjs → trigger-Cbyc41d_.mjs} +21 -6
  167. package/dist/trigger-yb_nFzPF.mjs +2 -0
  168. package/dist/{warm-progress-BuY-Fvfn.mjs → warm-progress-CA3TgT3-.mjs} +263 -156
  169. package/dist/web-CZ07gd77.mjs +2 -0
  170. package/dist/{web-BDBMxDpx.mjs → web-DKx6yoFA.mjs} +20 -14
  171. package/dist/web-run.mjs +13 -12
  172. package/dist/windows-report.d.mts +1 -0
  173. package/dist/windows-report.mjs +18 -0
  174. package/dist/windows-report.ps1 +43 -0
  175. package/dist/{workspace-state-DJt_MMvf.mjs → workspace-state-U08dEzhG.mjs} +62 -58
  176. package/dist/{workspaces-C36s2jb9.mjs → workspaces-CpANmBlq.mjs} +1723 -1286
  177. package/dist/{worktree-CgvJYJ-Q.mjs → worktree-CHecZ4Oq.mjs} +1097 -547
  178. package/dist/worktree-ZqZVjD9K.mjs +2 -0
  179. package/dist/xcode-BXn9-xYx.mjs +896 -0
  180. package/package.json +7 -5
  181. package/shim/android-audio/Main.java +24 -0
  182. package/shim/android-audio/README.md +17 -0
  183. package/shim/android-audio.jar +0 -0
  184. package/shim/android-optimizations.gradle +7 -5
  185. package/dist/activity-BSV745Kz.mjs +0 -629
  186. package/dist/api-qvOzWyfO.mjs +0 -154
  187. package/dist/api-run.mjs +0 -294
  188. package/dist/app-install-BIKtMfPq.mjs +0 -896
  189. package/dist/artifact-lifecycle-DzPpBYvK.mjs +0 -30
  190. package/dist/budget-f7516Zk0.mjs +0 -4106
  191. package/dist/build-facts-DcLv2HSd.d.mts +0 -111
  192. package/dist/cancellation-C_22VQTH.mjs +0 -24
  193. package/dist/client-qQAaXSUs.mjs +0 -1771
  194. package/dist/config-BYDxlMY3.mjs +0 -562
  195. package/dist/device-DuiPJQSn.mjs +0 -290
  196. package/dist/device-lease-BX1sJQ2E.mjs +0 -1224
  197. package/dist/device-remote-xRT0Vmo9.mjs +0 -1272
  198. package/dist/eas-session-ledger-Cm0Gwq2F.mjs +0 -207
  199. package/dist/exec-DqKo9GKJ.mjs +0 -268
  200. package/dist/git-DDfFzkMm.mjs +0 -45
  201. package/dist/launch-verify-B6Q8hZP-.mjs +0 -428
  202. package/dist/logs-BGrEUaEs.mjs +0 -383
  203. package/dist/macos-Ch5VJmcS.mjs +0 -584
  204. package/dist/metro-gateway-CX9Xlkq2.mjs +0 -103
  205. package/dist/miss-reason-mKzZ4VvN.mjs +0 -238
  206. package/dist/native-android-D5qc3-_v.mjs +0 -226
  207. package/dist/native-gradle-inputs-BsLRrl7u.mjs +0 -349
  208. package/dist/ndjson-Du3j0AQ9.d.mts +0 -17
  209. package/dist/plan-C4TjdPsR.mjs +0 -260
  210. package/dist/prebuild-DYbucPXy.mjs +0 -212
  211. package/dist/preview-78a9kR_-.mjs +0 -1011
  212. package/dist/react-native-build-CtCccJtb.mjs +0 -239
  213. package/dist/react-native-doctor-CfRnFfjs.mjs +0 -78
  214. package/dist/remote-cache-OyOyVIS3.mjs +0 -526
  215. package/dist/result-CaJg5Iat.mjs +0 -186
  216. package/dist/server-expo-Bigriskl.mjs +0 -2
  217. package/dist/settings-BORNaaCO.mjs +0 -402
  218. package/dist/settings-vk3mJGSm.d.mts +0 -13
  219. package/dist/spawn-claims-DVS5RkMS.mjs +0 -72
  220. package/dist/stage-KNTQopqv.mjs +0 -157
  221. package/dist/start-BWqzODpb.mjs +0 -1116
  222. package/dist/stim-desktop-BzBN2Em2.mjs +0 -63
  223. package/dist/swiftpm-macos-DRNVJWlb.mjs +0 -119
  224. package/dist/tailnet-Dh-qiYzG.mjs +0 -265
  225. package/dist/toolchain-BFkAcstd.mjs +0 -2
  226. package/dist/toolchain-DxSsNssu.mjs +0 -1657
  227. package/dist/trigger-9_USgmxz.mjs +0 -2
  228. package/dist/web-Dq-i3wzJ.mjs +0 -2
  229. package/dist/worktree-DpLdCHga.mjs +0 -2
  230. package/dist/{api-run.d.mts → doctor-fingerprint.d.mts} +0 -0
  231. package/dist/{errors-DzkMYh8Q.mjs → errors-ccaPc4ox.mjs} +2 -2
@@ -1,629 +0,0 @@
1
- import { k as process_identity_exports } from "./config-BYDxlMY3.mjs";
2
- import { t as getExecutor } from "./exec-DqKo9GKJ.mjs";
3
- import { i as listLeaseFiles, r as leaseIsExpired } from "./device-lease-BX1sJQ2E.mjs";
4
- import { r as readWorkspaceState$1, w as workspaceLogsDir$1 } from "./workspace-state-DJt_MMvf.mjs";
5
- import { closeSync, fstatSync, openSync, readFileSync, readSync, readdirSync, statSync } from "node:fs";
6
- import { basename, join, resolve } from "node:path";
7
- import { agentDeviceStateDirs, readViewedDevices } from "@stim-cli/core/state";
8
- import { homedir } from "node:os";
9
- //#region src/devices/automation-tools.ts
10
- const AUTOMATION_TOOLS = [
11
- {
12
- tool: "agent-browser",
13
- platforms: ["web"],
14
- cdp: /agent-browser/i
15
- },
16
- {
17
- tool: "agent-device",
18
- platforms: [
19
- "ios",
20
- "android",
21
- "web"
22
- ],
23
- host: /agent-device/i,
24
- cdp: /agent-device/i
25
- },
26
- {
27
- tool: "argent",
28
- platforms: [
29
- "ios",
30
- "android",
31
- "web"
32
- ],
33
- host: /\/bin\/[\w-]+\/(simulator-server(\.exe)?\s+(ios|android|android_device)|ax-service)\b|com\.argent\.androiddevtools/,
34
- instrumentation: /com\.argent\.androiddevtools/,
35
- cdp: /@swmansion\/argent\/dist\/tool-server/
36
- },
37
- {
38
- tool: "idb",
39
- platforms: ["ios"],
40
- host: /idb_companion/
41
- },
42
- {
43
- tool: "maestro",
44
- platforms: ["ios", "android"],
45
- host: /maestro/i
46
- },
47
- {
48
- tool: "appium",
49
- platforms: ["ios", "android"],
50
- host: /appium|WebDriverAgent/i
51
- },
52
- {
53
- tool: "xcodebuild",
54
- platforms: ["ios"],
55
- host: /\bxcodebuild\b.*\btest(-without-building)?\b/
56
- },
57
- {
58
- tool: "simctl",
59
- platforms: ["ios"],
60
- host: /\bsimctl\s+(io|spawn)\b/
61
- },
62
- {
63
- tool: "uiautomator",
64
- platforms: ["android"],
65
- instrumentation: /uiautomator/
66
- },
67
- {
68
- tool: "instrumentation",
69
- platforms: ["android"],
70
- instrumentation: /androidx\.test|\binstrument\b/
71
- },
72
- {
73
- tool: "chrome-devtools-mcp",
74
- platforms: ["web"],
75
- cdp: /chrome-devtools-mcp/i
76
- },
77
- {
78
- tool: "playwright",
79
- platforms: ["web"],
80
- cdp: /playwright/i
81
- },
82
- {
83
- tool: "puppeteer",
84
- platforms: ["web"],
85
- cdp: /puppeteer/i
86
- }
87
- ];
88
- const HOST_EXCLUSIONS = [/\bsimctl\s+spawn\b.*\blog\s+stream\b/, /\blogcat\b/];
89
- /** Stim's own DevTools clients: the browser supervisor, `stim-frames` in stim-server, Stim Desktop, the stim CLI. */
90
- const CDP_EXCLUSIONS = [/\bstim-(frames|server|web)\b|StimDesktop|\/stim(-cli)?\/(dist|bin)\/|\/bin\/stim(\s|$)|^stim(\s|$)/];
91
- function namesDevice(command, id) {
92
- const escaped = id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
93
- return new RegExp(`(^|[^A-Za-z0-9])${escaped}([^A-Za-z0-9]|$)`).test(command);
94
- }
95
- /** The tool a host process drives the device `id` with, or null when the command does not name the device. */
96
- function hostDriverTool(command, platform, id) {
97
- if (!namesDevice(command, id) || HOST_EXCLUSIONS.some((pattern) => pattern.test(command))) return null;
98
- return AUTOMATION_TOOLS.find((entry) => entry.platforms.includes(platform) && entry.host?.test(command))?.tool ?? null;
99
- }
100
- /** The tool behind an on-device process's arguments, or null when it is not instrumentation. */
101
- function instrumentationTool(args) {
102
- return AUTOMATION_TOOLS.find((entry) => entry.platforms.includes("android") && entry.instrumentation?.test(args))?.tool ?? null;
103
- }
104
- /**
105
- * The tool a DevTools client's command line names, or null for Stim's own clients. A client no entry names is
106
- * reported by its script or executable name.
107
- */
108
- function cdpClientTool(command) {
109
- if (CDP_EXCLUSIONS.some((pattern) => pattern.test(command))) return null;
110
- const known = AUTOMATION_TOOLS.find((entry) => entry.platforms.includes("web") && entry.cdp?.test(command));
111
- if (known) return known.tool;
112
- const [executable = "", script] = command.trim().split(/\s+/);
113
- const name = basename(executable);
114
- return (/^(node|bun|deno|python3?)$/.test(name) && script ? basename(script) : name) || "unknown DevTools client";
115
- }
116
- //#endregion
117
- //#region src/devices/activity.ts
118
- const ACTIVE_WINDOW_MS = 6e5;
119
- const LOG_TAIL_BYTES = 262144;
120
- function classifyActivity(evidence, now) {
121
- const last = evidence.recency.reduce((best, entry) => Number.isFinite(entry.at) && (!best || entry.at > best.at) ? entry : best, null);
122
- const recent = {};
123
- for (const { basis, at } of evidence.recency) if (Number.isFinite(at) && !(Date.parse(recent[basis] ?? "") >= at)) recent[basis] = new Date(at).toISOString();
124
- const lastActivityAt = last ? {
125
- lastActivityAt: new Date(last.at).toISOString(),
126
- recent
127
- } : {};
128
- const [first] = evidence.drivers;
129
- if (first) {
130
- const { basis: _basis, ...driver } = first;
131
- return {
132
- state: "driven",
133
- driver,
134
- ...lastActivityAt,
135
- basis: [...new Set(evidence.drivers.map((entry) => entry.basis))]
136
- };
137
- }
138
- if (evidence.unknown.length) return {
139
- state: "unknown",
140
- ...lastActivityAt,
141
- basis: [...new Set(evidence.unknown)]
142
- };
143
- return {
144
- state: Boolean(last && now - last.at < ACTIVE_WINDOW_MS) ? "active" : "idle",
145
- ...lastActivityAt,
146
- basis: [...new Set(evidence.recency.map((entry) => entry.basis))]
147
- };
148
- }
149
- function idleForMs(activity, now) {
150
- if (activity?.state !== "idle" || !activity.lastActivityAt) return null;
151
- const at = Date.parse(activity.lastActivityAt);
152
- return Number.isFinite(at) ? Math.max(0, now - at) : null;
153
- }
154
- function field(entry, pidKey, startKey) {
155
- const pid = entry[pidKey];
156
- const startTime = entry[startKey];
157
- if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0 || typeof startTime !== "string") return null;
158
- return {
159
- pid,
160
- startTime
161
- };
162
- }
163
- function parseObject(raw) {
164
- if (raw === null) return null;
165
- try {
166
- const parsed = JSON.parse(raw);
167
- return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
168
- } catch {
169
- return null;
170
- }
171
- }
172
- function parseAgentDeviceRecord(kind, path, raw) {
173
- const entry = parseObject(raw);
174
- const stem = basename(path, ".json");
175
- const device = entry?.device && typeof entry.device === "object" ? entry.device : null;
176
- const recordedId = kind === "claim" ? device?.id : entry?.deviceId;
177
- const deviceId = typeof recordedId === "string" && recordedId ? recordedId : kind === "runner-lease" ? stem : null;
178
- const createdAtMs = typeof entry?.createdAtMs === "number" ? entry.createdAtMs : null;
179
- return {
180
- path,
181
- kind,
182
- deviceId,
183
- session: kind === "claim" && typeof entry?.session === "string" && entry.session ? entry.session : null,
184
- workspace: kind === "claim" && typeof entry?.workspace === "string" && entry.workspace ? entry.workspace : null,
185
- stateDir: kind === "claim" && typeof entry?.stateDir === "string" && entry.stateDir ? entry.stateDir : null,
186
- deviceName: kind === "claim" && typeof device?.name === "string" ? device.name : null,
187
- readable: Boolean(entry && deviceId),
188
- owner: entry ? field(entry, "ownerPid", "ownerStartTime") : null,
189
- runner: entry && kind === "runner-lease" ? field(entry, "runnerPid", "runnerStartTime") : null,
190
- claimProtocol: kind === "runner-lease" && entry?.deviceClaimProtocol === 1,
191
- createdAtMs,
192
- xctestrunPath: typeof entry?.xctestrunPath === "string" ? entry.xctestrunPath : null
193
- };
194
- }
195
- function processMatches(entry, startOf) {
196
- const start = startOf(entry.pid);
197
- if (start.status === "gone") return "dead";
198
- if (start.status === "unknown") return "unknown";
199
- const recorded = Date.parse(entry.startTime);
200
- if (!Number.isFinite(recorded)) return "unknown";
201
- return Math.floor(start.startedAtMs / 1e3) === Math.floor(recorded / 1e3) ? "live" : "dead";
202
- }
203
- function agentDeviceDaemon(stateDir, startOf = process_identity_exports.inspectProcessStart) {
204
- let raw;
205
- try {
206
- raw = readFileSync(join(stateDir, "daemon.json"), "utf8");
207
- } catch (error) {
208
- return error.code === "ENOENT" ? "none" : "unknown";
209
- }
210
- const entry = parseObject(raw);
211
- const owner = entry && field(entry, "pid", "processStartTime");
212
- return owner ? processMatches(owner, startOf) : "unknown";
213
- }
214
- function agentDeviceLiveness(record, startOf) {
215
- const results = (record.kind === "claim" ? [record.owner] : [record.owner, record.runner]).map((entry) => entry ? processMatches(entry, startOf) : "unknown");
216
- if (results.includes("dead")) return "dead";
217
- if (!record.readable || results.includes("unknown")) return "unknown";
218
- return "live";
219
- }
220
- const HOST_PROCESS_COLUMNS = "pid=,ppid=,rss=,%cpu=,lstart=,command=";
221
- function parseProcessTable(output) {
222
- const rows = [];
223
- for (const line of output.split("\n")) {
224
- const match = /^\s*(\d+)\s+(\d+)\s+(\d+)\s+(\d+(?:[.,]\d+)?)\s+(\w{3}\s+\w{3}\s+\d+\s+\d{1,2}:\d{2}:\d{2}\s+\d{4})\s+(.*)$/.exec(line);
225
- if (!match) continue;
226
- const at = Date.parse(match[5]);
227
- rows.push({
228
- pid: Number(match[1]),
229
- ppid: Number(match[2]),
230
- rssKb: Number(match[3]),
231
- cpuPercent: Number(match[4].replace(",", ".")),
232
- startedAt: Number.isFinite(at) ? new Date(at).toISOString() : null,
233
- command: match[6]
234
- });
235
- }
236
- return rows;
237
- }
238
- function parseAndroidInstrumentation(output) {
239
- const found = [];
240
- for (const line of output.split("\n")) {
241
- const match = /^\s*(\d+)\s+(.*)$/.exec(line);
242
- if (!match) continue;
243
- const tool = instrumentationTool(match[2]);
244
- if (tool) found.push({
245
- pid: Number(match[1]),
246
- tool
247
- });
248
- }
249
- return found;
250
- }
251
- function latestDeviceLogAt(lines, target) {
252
- return latestRecordAt(lines, (record) => {
253
- if (record.src !== "device" || record.platform !== target.platform || !isDeviceRecord(record)) return false;
254
- if (target.slot === "default") return record.slot === void 0;
255
- return record.slot === target.slot && (record.deviceId === void 0 || record.deviceId === target.id);
256
- });
257
- }
258
- function latestBundleRequestAt(lines, platform) {
259
- return latestRecordAt(lines, (record) => record.event === "bundle_response_started" && record.platform === platform);
260
- }
261
- function latestRecordAt(lines, matches) {
262
- for (let i = lines.length - 1; i >= 0; i--) {
263
- const record = parseObject(lines[i]);
264
- if (record && typeof record.ts === "number" && matches(record)) return record.ts;
265
- }
266
- return null;
267
- }
268
- function isDeviceRecord(record) {
269
- return !(typeof record.event === "string" && record.event.startsWith("collector_"));
270
- }
271
- /** The last lines of the file at `path`, at most its final 256 KiB, or null when it cannot be read. */
272
- function tailLines(path) {
273
- let fd;
274
- try {
275
- fd = openSync(path, "r");
276
- const size = fstatSync(fd).size;
277
- const length = Math.min(size, LOG_TAIL_BYTES);
278
- const buffer = Buffer.alloc(length);
279
- readSync(fd, buffer, 0, length, size - length);
280
- const lines = buffer.toString("utf8").split("\n");
281
- return length < size ? lines.slice(1) : lines;
282
- } catch {
283
- return null;
284
- } finally {
285
- if (fd !== void 0) closeSync(fd);
286
- }
287
- }
288
- function envDir(name) {
289
- const value = process.env[name]?.trim();
290
- return value ? resolve(value) : null;
291
- }
292
- function agentDeviceDirs(home) {
293
- const root = join(home, ".agent-device");
294
- const leaseDirs = [envDir("AGENT_DEVICE_IOS_RUNNER_LEASE_DIR") ?? join(root, "apple-runner", "leases"), join(root, "ios-runner", "leases")];
295
- return [{
296
- kind: "claim",
297
- dir: envDir("AGENT_DEVICE_CLAIMS_DIR") ?? join(root, "device-claims")
298
- }, ...[...new Set(leaseDirs)].map((dir) => ({
299
- kind: "runner-lease",
300
- dir
301
- }))];
302
- }
303
- /**
304
- * When an agent-device session last recorded an event: its events file's modification time. agent-device names a
305
- * session's directory after the session with every character outside `[a-zA-Z0-9._-]` replaced by `_`.
306
- */
307
- function agentSessionActedAt(home, session, stateDir) {
308
- let latest = null;
309
- for (const root of stateDir ? [stateDir] : agentDeviceStateDirs(home)) try {
310
- const at = statSync(join(root, "sessions", session.replaceAll(/[^a-zA-Z0-9._-]/g, "_"), "events.ndjson")).mtimeMs;
311
- latest = latest === null ? at : Math.max(latest, at);
312
- } catch {}
313
- return latest;
314
- }
315
- function readAgentDeviceRecords(home) {
316
- return agentDeviceDirs(home).flatMap(({ kind, dir }) => {
317
- let names;
318
- try {
319
- names = readdirSync(dir).filter((name) => name.endsWith(".json"));
320
- } catch {
321
- return [];
322
- }
323
- return names.map((name) => {
324
- const path = join(dir, name);
325
- let raw = null;
326
- try {
327
- raw = readFileSync(path, "utf8");
328
- } catch {}
329
- return parseAgentDeviceRecord(kind, path, raw);
330
- });
331
- });
332
- }
333
- function isClaimProtocolRunner(record, row) {
334
- if (!record.claimProtocol || record.runner?.pid !== row.pid || row.startedAt === null) return false;
335
- const recorded = Date.parse(record.runner.startTime);
336
- return Math.floor(recorded / 1e3) === Math.floor(Date.parse(row.startedAt) / 1e3);
337
- }
338
- function lsofArgs(port) {
339
- return [
340
- "-nP",
341
- `-iTCP:${port}`,
342
- "-sTCP:ESTABLISHED",
343
- "-Fpn"
344
- ];
345
- }
346
- function lsofNoMatch(error) {
347
- const stdout = error.stdout;
348
- return error.status === 1 && (stdout === "" || stdout === void 0) ? "" : null;
349
- }
350
- function createDeviceProcessTables() {
351
- const exec = getExecutor();
352
- let host;
353
- const android = /* @__PURE__ */ new Map();
354
- const tcp = /* @__PURE__ */ new Map();
355
- return {
356
- tcpConnections(port) {
357
- if (!tcp.has(port)) {
358
- let output;
359
- try {
360
- output = exec.runFile("lsof", lsofArgs(port), { timeoutMs: 5e3 });
361
- } catch (error) {
362
- output = lsofNoMatch(error);
363
- }
364
- tcp.set(port, output);
365
- }
366
- return tcp.get(port) ?? null;
367
- },
368
- host() {
369
- if (host === void 0) {
370
- const output = exec.runFileQuiet("ps", [
371
- "-axww",
372
- "-o",
373
- HOST_PROCESS_COLUMNS
374
- ], { timeoutMs: 1e4 });
375
- host = output === null ? null : parseProcessTable(output);
376
- }
377
- return host;
378
- },
379
- android(serial) {
380
- if (!android.has(serial)) android.set(serial, exec.runFileQuiet("adb", [
381
- "-s",
382
- serial,
383
- "shell",
384
- "ps",
385
- "-A",
386
- "-o",
387
- "PID,ARGS"
388
- ], { timeoutMs: 5e3 }));
389
- return android.get(serial) ?? null;
390
- }
391
- };
392
- }
393
- function workspaceDeviceRecency(root) {
394
- const recency = [];
395
- const usedAt = Date.parse(String(readWorkspaceState$1(root)?.lastUsedAt ?? ""));
396
- if (Number.isFinite(usedAt)) recency.push({
397
- basis: "workspace-use",
398
- at: usedAt
399
- });
400
- for (const file of ["client.ndjson", "device.ndjson"]) try {
401
- recency.push({
402
- basis: "device-log",
403
- at: statSync(join(workspaceLogsDir$1(root), file)).mtimeMs
404
- });
405
- } catch {}
406
- return recency;
407
- }
408
- /** The newest workspace use or change to its in-app or native device logs. */
409
- function workspaceDeviceLastUseAt(root) {
410
- const times = workspaceDeviceRecency(root).map(({ at }) => at).filter(Number.isFinite);
411
- return times.length ? Math.max(...times) : NaN;
412
- }
413
- function createActivityReader({ now = Date.now(), home = homedir(), startOf = process_identity_exports.inspectProcessStart, leaseFiles = listLeaseFiles, tables = createDeviceProcessTables(), viewers = readViewedDevices } = {}) {
414
- let agentDevice;
415
- let stimLeases;
416
- let viewed;
417
- const logs = /* @__PURE__ */ new Map();
418
- const log = (path) => {
419
- if (!logs.has(path)) logs.set(path, tailLines(path));
420
- return logs.get(path) ?? null;
421
- };
422
- return (target) => {
423
- const evidence = {
424
- drivers: [],
425
- unknown: [],
426
- recency: []
427
- };
428
- agentDevice ??= readAgentDeviceRecords(home).map((record) => ({
429
- record,
430
- liveness: agentDeviceLiveness(record, startOf)
431
- }));
432
- for (const { record, liveness } of agentDevice) {
433
- if (record.deviceId !== null && record.deviceId !== target.id) continue;
434
- if (record.claimProtocol) continue;
435
- const basis = record.kind === "claim" ? "agent-device-claim" : "agent-device-lease";
436
- if (liveness === "live") {
437
- evidence.drivers.push({
438
- basis,
439
- tool: "agent-device",
440
- pid: record.owner?.pid ?? null,
441
- since: record.createdAtMs !== null ? new Date(record.createdAtMs).toISOString() : null
442
- });
443
- const actedAt = record.session ? agentSessionActedAt(home, record.session, record.stateDir) : null;
444
- if (actedAt !== null) evidence.recency.push({
445
- basis: "agent-action",
446
- at: actedAt
447
- });
448
- } else if (liveness === "unknown") evidence.unknown.push(basis);
449
- }
450
- try {
451
- stimLeases ??= leaseFiles();
452
- } catch {
453
- stimLeases = [];
454
- evidence.unknown.push("device-lock");
455
- }
456
- for (const entry of stimLeases) {
457
- if (entry.platform !== target.platform || entry.id !== target.id) continue;
458
- if (!entry.lease) evidence.unknown.push("device-lock");
459
- else if (!leaseIsExpired(entry.lease, now)) evidence.drivers.push({
460
- basis: "device-lock",
461
- tool: "stim device lock",
462
- pid: null,
463
- since: entry.lease.grantedAt
464
- });
465
- }
466
- viewed ??= viewers();
467
- if (viewed.some((device) => device.platform === target.platform && device.id === target.id)) evidence.recency.push({
468
- basis: "viewer",
469
- at: now
470
- });
471
- const processes = tables.host();
472
- if (processes === null) evidence.unknown.push("driver-process");
473
- for (const row of processes ?? []) {
474
- if (agentDevice.some(({ record }) => isClaimProtocolRunner(record, row))) continue;
475
- const tool = hostDriverTool(row.command, target.platform, target.id);
476
- if (tool) evidence.drivers.push({
477
- basis: "driver-process",
478
- tool,
479
- pid: row.pid,
480
- since: row.startedAt
481
- });
482
- }
483
- if (target.platform === "android") {
484
- const output = tables.android(target.id);
485
- if (output === null) evidence.unknown.push("instrumentation");
486
- for (const { pid, tool } of parseAndroidInstrumentation(output ?? "")) evidence.drivers.push({
487
- basis: "instrumentation",
488
- tool,
489
- pid,
490
- since: null
491
- });
492
- }
493
- if (target.workspace) {
494
- const dir = workspaceLogsDir$1(target.workspace);
495
- const deviceAt = latestDeviceLogAt(log(join(dir, "device.ndjson")) ?? [], target);
496
- if (deviceAt !== null) evidence.recency.push({
497
- basis: "device-log",
498
- at: deviceAt
499
- });
500
- const bundleAt = latestBundleRequestAt(log(join(dir, "metro.ndjson")) ?? [], target.platform);
501
- if (bundleAt !== null) evidence.recency.push({
502
- basis: "metro-bundle",
503
- at: bundleAt
504
- });
505
- const usedAt = Date.parse(String(readWorkspaceState$1(target.workspace)?.lastUsedAt ?? ""));
506
- if (Number.isFinite(usedAt)) evidence.recency.push({
507
- basis: "workspace-use",
508
- at: usedAt
509
- });
510
- }
511
- return classifyActivity(evidence, now);
512
- };
513
- }
514
- function workspaceActivity(workspace, now = Date.now()) {
515
- const dir = workspaceLogsDir$1(workspace);
516
- const state = readWorkspaceState$1(workspace);
517
- const recency = [];
518
- const deviceAt = latestRecordAt(tailLines(join(dir, "device.ndjson")) ?? [], (record) => record.src === "device" && isDeviceRecord(record));
519
- if (deviceAt !== null) recency.push({
520
- basis: "device-log",
521
- at: deviceAt
522
- });
523
- const bundleAt = latestRecordAt(tailLines(join(dir, "metro.ndjson")) ?? [], (record) => record.event === "bundle_response_started");
524
- if (bundleAt !== null) recency.push({
525
- basis: "metro-bundle",
526
- at: bundleAt
527
- });
528
- for (const [basis, value] of [["workspace-use", state?.lastUsedAt], ["supervisor-start", state?.supervisor?.startedAt]]) {
529
- const at = Date.parse(String(value ?? ""));
530
- if (Number.isFinite(at)) recency.push({
531
- basis,
532
- at
533
- });
534
- }
535
- return classifyActivity({
536
- drivers: [],
537
- unknown: [],
538
- recency
539
- }, now);
540
- }
541
- /**
542
- * The pids of processes connected to loopback `port` as clients, from `lsof -Fpn` output: a connection whose remote
543
- * end is the port. Chrome's own accepted sockets have the port as their local end and are skipped.
544
- */
545
- function parseTcpClients(output, port) {
546
- const pids = /* @__PURE__ */ new Set();
547
- let pid = null;
548
- for (const line of output.split("\n")) if (line.startsWith("p")) pid = Number(line.slice(1));
549
- else if (line.startsWith("n") && pid !== null && Number.isInteger(pid)) {
550
- const remote = line.slice(1).split("->")[1];
551
- if (remote && Number(remote.slice(remote.lastIndexOf(":") + 1)) === port) pids.add(pid);
552
- }
553
- return [...pids];
554
- }
555
- function webClientPids(connections, target) {
556
- return parseTcpClients(connections, target.port).filter((pid) => !target.ownPids.includes(pid));
557
- }
558
- function webDrivers(clients, processes) {
559
- return clients.flatMap((pid) => {
560
- const row = processes.find((candidate) => candidate.pid === pid);
561
- const tool = row ? cdpClientTool(row.command) : "unknown DevTools client";
562
- return tool ? [{
563
- tool,
564
- pid,
565
- since: row?.startedAt ?? null
566
- }] : [];
567
- });
568
- }
569
- /**
570
- * The DevTools clients of the owned browser that are not Stim's, read without blocking the event loop; null when
571
- * lsof or ps could not be read.
572
- */
573
- async function probeWebDrivers(target) {
574
- const exec = getExecutor();
575
- let connections;
576
- try {
577
- connections = await exec.runFileAsync("lsof", lsofArgs(target.port), { timeoutMs: 5e3 });
578
- } catch (error) {
579
- connections = lsofNoMatch(error);
580
- }
581
- if (connections === null) return null;
582
- const clients = webClientPids(connections, target);
583
- if (!clients.length) return [];
584
- let table;
585
- try {
586
- table = await exec.runFileAsync("ps", [
587
- "-axww",
588
- "-o",
589
- HOST_PROCESS_COLUMNS
590
- ], { timeoutMs: 5e3 });
591
- } catch {
592
- return null;
593
- }
594
- return webDrivers(clients, parseProcessTable(table));
595
- }
596
- /**
597
- * The owned browser's activity: a DevTools client other than Stim's is a driver (basis `cdp-client`). Recency comes
598
- * from the newest agent action the browser supervisor recorded (basis `agent-action`) and the newest other page
599
- * record (basis `page-log`).
600
- */
601
- function readWebActivity(target, tables, now = Date.now()) {
602
- const evidence = {
603
- drivers: [],
604
- unknown: [],
605
- recency: []
606
- };
607
- const connections = tables.tcpConnections(target.port);
608
- const clients = connections === null ? [] : webClientPids(connections, target);
609
- const processes = clients.length ? (tables.clients ?? tables.host)() : [];
610
- if (connections === null || processes === null) evidence.unknown.push("cdp-client");
611
- else for (const driver of webDrivers(clients, processes)) evidence.drivers.push({
612
- ...driver,
613
- basis: "cdp-client"
614
- });
615
- const lines = tailLines(join(workspaceLogsDir$1(target.workspace), "web.ndjson")) ?? [];
616
- const actionAt = latestRecordAt(lines, (record) => record.src === "agent");
617
- if (actionAt !== null) evidence.recency.push({
618
- basis: "agent-action",
619
- at: actionAt
620
- });
621
- const pageAt = latestRecordAt(lines, (record) => record.src !== "agent");
622
- if (pageAt !== null) evidence.recency.push({
623
- basis: "page-log",
624
- at: pageAt
625
- });
626
- return classifyActivity(evidence, now);
627
- }
628
- //#endregion
629
- export { envDir as a, probeWebDrivers as c, readWebActivity as d, tailLines as f, createDeviceProcessTables as i, processMatches as l, workspaceDeviceLastUseAt as m, agentDeviceLiveness as n, idleForMs as o, workspaceActivity as p, createActivityReader as r, parseAgentDeviceRecord as s, agentDeviceDaemon as t, readAgentDeviceRecords as u };