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.
- package/README.md +141 -8
- package/dist/acquire-artifact-Co2k4f7O.mjs +171 -0
- package/dist/act-DsuqEkiM.mjs +2801 -0
- package/dist/activity-CMLmzp7o.mjs +1397 -0
- package/dist/{agent-device-usage-output-Dzgv6lgR.mjs → agent-device-usage-output-DUFaTMdd.mjs} +23 -67
- package/dist/{android-DCKZrNvV.mjs → android-ByRMUoiJ.mjs} +157 -93
- package/dist/{android-Mz_Inn3w.mjs → android-C7sVmyI9.mjs} +299 -116
- package/dist/{android-Dlzxshgp.mjs → android-DGkNqa_c.mjs} +5 -5
- package/dist/{android-HqP1_vB_.mjs → android-DR5lZ2Az.mjs} +2 -2
- package/dist/android-cas-compiler.mjs +2 -2
- package/dist/{android-cas-Bl-cLJBk.mjs → android-cas-ngferVq2.mjs} +7 -6
- package/dist/android-project-BCAAmMwz.mjs +12 -0
- package/dist/android-project-DVWyCbWU.d.mts +391 -0
- package/dist/api.d.mts +810 -64
- package/dist/api.mjs +782 -1
- package/dist/{artifact-HSwkIWEQ.mjs → artifact-8EY8SAPw.mjs} +240 -213
- package/dist/{artifact-D3czlUvT.mjs → artifact-DJPy518Y.mjs} +203 -164
- package/dist/artifact-platform-CXcmX_j3.mjs +27 -0
- package/dist/{browser-web-CA-F1GQo.mjs → browser-web-Bcv99PBM.mjs} +194 -64
- package/dist/budget-Cvwn54qV.mjs +9285 -0
- package/dist/{build-DYDbfkk5.mjs → build-CabC3G23.mjs} +153 -98
- package/dist/build-cache-Dv7RN200.mjs +602 -0
- package/dist/build-plan-DUC8Ka9y.mjs +248 -0
- package/dist/{cache-manifest-XH-fvDUj.mjs → cache-manifest-DSeQjt-Q.mjs} +2 -2
- package/dist/cache-manifest.mjs +1 -1
- package/dist/{ccache-zdKiYQ3E.mjs → ccache-Btwc36-I.mjs} +10 -9
- package/dist/{cdp-Dq_ypAlJ.mjs → cdp-3fwICjzi.mjs} +18 -5
- package/dist/{chrome-BnzZMqsR.mjs → chrome-Bbw689-6.mjs} +7 -4
- package/dist/{cli-CLP3diBm.mjs → cli-CHZa9Lvk.mjs} +20 -20
- package/dist/cli.mjs +1 -1
- package/dist/client-OyRoEuSr.mjs +1577 -0
- package/dist/collector-run.d.mts +4 -40
- package/dist/collector-run.mjs +9 -8
- package/dist/{command-output-BTy8hZ0F.mjs → command-output-gwpm28fu.mjs} +1 -1
- package/dist/config-DlrsduwG.mjs +955 -0
- package/dist/{created-devices-Dzd5C2LF.mjs → created-devices-x9rN6bhs.mjs} +14 -4
- package/dist/{dependency-state-DG0p31-y.mjs → dependency-state-1I9KZT1Y.mjs} +20 -5
- package/dist/{detached-entry-B9C_zeQC.mjs → detached-entry-BwNEtIrP.mjs} +1 -1
- package/dist/{dev-client-DAWVIGBu.mjs → dev-client-BSDR5h3F.mjs} +2 -2
- package/dist/{device-BECOiufl.mjs → device-B-L3Fbxy.mjs} +91 -34
- package/dist/device-DklWZLqb.mjs +1068 -0
- package/dist/{device-capacity-CBUAcRyQ.mjs → device-capacity-DK5_EwRS.mjs} +42 -13
- package/dist/device-host-worker.mjs +76 -79
- package/dist/{device-ios-COSi6oS1.mjs → device-ios-DoB6KFCO.mjs} +77 -51
- package/dist/{device-lease-run-Cw2M4z51.mjs → device-lease-run-xJPQ_QQG.mjs} +14 -26
- package/dist/{device-pool-Bf-pOhSw.mjs → device-pool-BMkdsefq.mjs} +5 -5
- package/dist/{doctor-kfMBnUw6.mjs → doctor-Bo7BXLux.mjs} +271 -320
- package/dist/{doctor-CB8oZKCk.mjs → doctor-D5_EzwfA.mjs} +186 -91
- package/dist/doctor-fingerprint-DZLoYFVb.mjs +16 -0
- package/dist/doctor-fingerprint.mjs +19 -0
- package/dist/doctor-thjWAV0z.mjs +2 -0
- package/dist/{doctor-watchman-BRyV2adA.mjs → doctor-watchman-N2wDotwQ.mjs} +40 -21
- package/dist/{eas-build-JyfqyHfC.mjs → eas-build-CwknaQYj.mjs} +53 -20
- package/dist/{build-plan-B7SZsc2N.mjs → eas-fallback-CSgAulr5.mjs} +41 -214
- package/dist/{watchman-CPQFZLXY.mjs → eas-session-ledger-DlY_serQ.mjs} +230 -11
- package/dist/{error-diagnostics-BR677IDM.mjs → error-diagnostics-DBWO2rxE.mjs} +172 -82
- package/dist/exec-DEoAhcze.mjs +858 -0
- package/dist/exec-DnYc4HGH.d.mts +78 -0
- package/dist/{gc-qWOMdnER.mjs → gc-CXxN-4SE.mjs} +1091 -1029
- package/dist/gc-DnNDQyaP.mjs +3 -0
- package/dist/{guide-G9cAbVAc.mjs → guide-Br0LEfKy.mjs} +1165 -297
- package/dist/{hosted-android-C3MHGld1.mjs → hosted-android-B-9f-jkd.mjs} +10 -8
- package/dist/{hosted-client-ZEKpS9vw.mjs → hosted-client-DZAPrcro.mjs} +34 -19
- package/dist/{hosted-ios-l-o3iM9J.mjs → hosted-ios-CsCS21hn.mjs} +1 -1
- package/dist/{hosted-logs-EzQM7-3Z.mjs → hosted-logs-FIRx9X2f.mjs} +77 -43
- package/dist/{hosted-macos-BACVAVqE.mjs → hosted-macos-_awYSpfv.mjs} +35 -22
- package/dist/{hosted-native-A4s1QPXe.mjs → hosted-native-BdzE668-.mjs} +49 -27
- package/dist/idle-C4cZ757K.d.mts +24 -0
- package/dist/{idle-shutdown-DtxhPTKe.mjs → idle-shutdown-DDg3SdvY.mjs} +11 -10
- package/dist/ios-CDvlmUs7.d.mts +24 -0
- package/dist/{ios-BwVCF7oA.mjs → ios-Ds1clbIt.mjs} +8 -8
- package/dist/{ios-device-D7pi2Sca.mjs → ios-device--h_-8ENa.mjs} +51 -26
- package/dist/{ios-device-B5veSDDQ.mjs → ios-device-BXZ0c7Kb.mjs} +1 -1
- package/dist/{ios-RkW4pnQf.mjs → ios-hcBpnEGk.mjs} +200 -93
- package/dist/{ios-Ce7bc7br.mjs → ios-pm4nL6By.mjs} +160 -108
- package/dist/{ios-project-K9hY_Jab.mjs → ios-project-CZhKODF3.mjs} +13 -13
- package/dist/ios-signing-BtAffm0A.mjs +489 -0
- package/dist/{ios-state-CBLe1xYw.mjs → ios-state-Dtw5K2aI.mjs} +1 -1
- package/dist/{ios-nOLJGVdy.mjs → ios-xtlRHaeB.mjs} +1 -1
- package/dist/{js-swap-Bb3nsS07.mjs → js-swap-Bwhh4S7V.mjs} +30 -25
- package/dist/{launch-C3qJ6Agb.mjs → launch-BjxemNpK.mjs} +85 -543
- package/dist/{launch-F4sOqAhB.mjs → launch-CCzXlc8r.mjs} +91 -90
- package/dist/logs-BfwwadsZ.mjs +479 -0
- package/dist/logs-jTS_lHSo.mjs +248 -0
- package/dist/{macos-D7uDvO-z.mjs → macos-DVlSSyUg.mjs} +1 -1
- package/dist/macos-NfV2D7dO.mjs +694 -0
- package/dist/macos-run.mjs +1 -1
- package/dist/maintenance-run.mjs +123 -248
- package/dist/{metro-DnCEjCxs.mjs → metro-DiXtA3Ty.mjs} +107 -30
- package/dist/metro-gateway-CKZqKqx7.mjs +209 -0
- package/dist/{named-ports-4WopRPg-.mjs → named-ports-DkEzOfzO.mjs} +42 -90
- package/dist/native-android-CqgnOgsT.mjs +645 -0
- package/dist/native-gradle-artifact-inputs-DHFnmrVf.mjs +270 -0
- package/dist/native-gradle-inputs-Dnh84Zbd.mjs +211 -0
- package/dist/native-inputs-TRTTTRxt.mjs +91 -0
- package/dist/native-run-NwUuxbkg.mjs +276 -0
- package/dist/{native-runtime-k8dTIrbK.mjs → native-runtime-B7KIafpM.mjs} +11 -9
- package/dist/native-source-Y0yLhFyQ.mjs +133 -0
- package/dist/{native-xcode-inputs-CykopJdM.mjs → native-xcode-inputs-D_VOfFL7.mjs} +26 -18
- package/dist/{native-xcode-ios-Bbf30Gm0.mjs → native-xcode-ios-BYDOHWLN.mjs} +104 -60
- package/dist/{ndjson-GOnbyvso.mjs → ndjson-CgE_o3Dl.mjs} +3 -3
- package/dist/offload-worker.d.mts +59 -41
- package/dist/offload-worker.mjs +478 -115
- package/dist/operation-exec-BW0em61G.mjs +171 -0
- package/dist/{ownership-DCtw_2IA.mjs → ownership-C5fo5Edb.mjs} +3 -3
- package/dist/{page-DRHy329N.mjs → page-DBL2PiUU.mjs} +12 -5
- package/dist/paths-BsJMoPP2.mjs +12 -0
- package/dist/paths-DQtTgsBf.mjs +42 -0
- package/dist/{placement-log-MOfPVgaM.mjs → placement-log-BnGgJRRZ.mjs} +5 -5
- package/dist/{plan-placement-V0TdzYXp.mjs → plan-placement-DIsMtN-d.mjs} +15 -11
- package/dist/{ports-DdSUicVo.mjs → ports-Cy1RkmuQ.mjs} +3 -3
- package/dist/prebuild-D4JoEAEs.mjs +484 -0
- package/dist/{project-_phNIJfs.mjs → project-wM_XFTvE.mjs} +65 -37
- package/dist/{pull-request-CQ8sPbZa.mjs → pull-request-W1IuLXDt.mjs} +102 -20
- package/dist/pull-request-eODyIqZF.d.mts +124 -0
- package/dist/pull-requests.d.mts +2 -120
- package/dist/pull-requests.mjs +2 -2
- package/dist/{react-native-android-CM1XRDwv.mjs → react-native-android-6OZ7MSM7.mjs} +121 -72
- package/dist/{gradle-DSrXb6lG.mjs → react-native-build-Dvd8hC21.mjs} +292 -15
- package/dist/react-native-doctor-DsoSF1Y9.mjs +234 -0
- package/dist/{react-native-ios-Dhq_eiYQ.mjs → react-native-ios-4u1Rn-GR.mjs} +71 -39
- package/dist/{recordings-D0d5aQt0.mjs → recordings-CQmfzAh7.mjs} +12 -9
- package/dist/registration-BcRgF6Ox.mjs +51 -0
- package/dist/{reload-C8JhxjSh.mjs → reload-BzkYabB-.mjs} +94 -47
- package/dist/reload-D7AVlb8N.mjs +2 -0
- package/dist/{remote-BiR6aYjy.mjs → remote-DjGDmlTZ.mjs} +26 -18
- package/dist/result-D2Ykz_iD.mjs +435 -0
- package/dist/{run-BtPgpKks.mjs → run-DidHghD1.mjs} +5 -5
- package/dist/selection-DSMbWEX2.mjs +620 -0
- package/dist/{server-bare-R2m_gsH8.mjs → server-bare-CafzuyFB.mjs} +3 -4
- package/dist/{server-command-CTtCkmcQ.mjs → server-command-C6QjeupS.mjs} +14 -7
- package/dist/{server-expo-DsguMGUF.mjs → server-expo-CrjB29pq.mjs} +54 -11
- package/dist/server-expo-D58c9L0M.mjs +2 -0
- package/dist/{settings-B717odTD.mjs → settings-C7O8A6ZI.mjs} +309 -119
- package/dist/settings-DpR-1Wnn.mjs +114 -0
- package/dist/settings-write-CzD60rOD.mjs +360 -0
- package/dist/settings.schema.json +176 -16
- package/dist/{simslim-CCr3rE-A.mjs → simslim-BNckWpXi.mjs} +14 -12
- package/dist/{slot-launch-DPt0m9Nd.mjs → slot-launch-CbfmNgM6.mjs} +15 -20
- package/dist/{spawn-entry-Dcb7sDUz.mjs → spawn-entry-jw19m8Nl.mjs} +0 -1
- package/dist/stage-Bps5oius.mjs +200 -0
- package/dist/{start-TXeMmmO2.mjs → start-Br-oxqMD.mjs} +1 -1
- package/dist/start-EojN4WFz.mjs +1364 -0
- package/dist/{state-D1Icyjlu.mjs → state--smjFSTL.mjs} +55 -13
- package/dist/{state-CG_OFoaA.mjs → state-08I3hw3_.mjs} +3 -2
- package/dist/{stats-BoY5sEPU.mjs → stats-D3GerlFW.mjs} +7 -13
- package/dist/stats-report-BzaPrRm6.mjs +16 -0
- package/dist/{status-BTA7kKiQ.mjs → status-BRROykC8.mjs} +7 -5
- package/dist/status-EvrK72L2.mjs +2 -0
- package/dist/{status-WgFbkRzj.mjs → status-WBDajew2.mjs} +554 -452
- package/dist/{status-watch-C23ILtf9.mjs → status-watch-Bg_u-pwR.mjs} +222 -25
- package/dist/status-worker.d.mts +1 -0
- package/dist/status-worker.mjs +19 -0
- package/dist/stim-desktop-D5OGpYZM.mjs +112 -0
- package/dist/{stop-DR6VoDIk.mjs → stop-DTZ9uTw3.mjs} +2 -2
- package/dist/{stop-DPEhunlw.mjs → stop-Dky10AEJ.mjs} +33 -23
- package/dist/{stop-BNmBMi1F.mjs → stop-Mv6W9FAk.mjs} +137 -98
- package/dist/supervisor-run.d.mts +8 -17
- package/dist/supervisor-run.mjs +56 -28
- package/dist/{support-CwjbFs9H.mjs → support-CNioewsd.mjs} +14 -14
- package/dist/{support-DMTqj3Hm.mjs → support-yUiOjnVY.mjs} +20 -13
- package/dist/swiftpm-artifact-inputs-DFcGsXDP.mjs +153 -0
- package/dist/swiftpm-macos-BIak-Rxv.mjs +532 -0
- package/dist/toolchain-BY8X8HXx.mjs +2 -0
- package/dist/toolchain-DpJMHq0n.mjs +876 -0
- package/dist/{trigger-CigAYjeL.mjs → trigger-Cbyc41d_.mjs} +21 -6
- package/dist/trigger-yb_nFzPF.mjs +2 -0
- package/dist/{warm-progress-BuY-Fvfn.mjs → warm-progress-CA3TgT3-.mjs} +263 -156
- package/dist/web-CZ07gd77.mjs +2 -0
- package/dist/{web-BDBMxDpx.mjs → web-DKx6yoFA.mjs} +20 -14
- package/dist/web-run.mjs +13 -12
- package/dist/windows-report.d.mts +1 -0
- package/dist/windows-report.mjs +18 -0
- package/dist/windows-report.ps1 +43 -0
- package/dist/{workspace-state-DJt_MMvf.mjs → workspace-state-U08dEzhG.mjs} +62 -58
- package/dist/{workspaces-C36s2jb9.mjs → workspaces-CpANmBlq.mjs} +1723 -1286
- package/dist/{worktree-CgvJYJ-Q.mjs → worktree-CHecZ4Oq.mjs} +1097 -547
- package/dist/worktree-ZqZVjD9K.mjs +2 -0
- package/dist/xcode-BXn9-xYx.mjs +896 -0
- package/package.json +7 -5
- package/shim/android-audio/Main.java +24 -0
- package/shim/android-audio/README.md +17 -0
- package/shim/android-audio.jar +0 -0
- package/shim/android-optimizations.gradle +7 -5
- package/dist/activity-BSV745Kz.mjs +0 -629
- package/dist/api-qvOzWyfO.mjs +0 -154
- package/dist/api-run.mjs +0 -294
- package/dist/app-install-BIKtMfPq.mjs +0 -896
- package/dist/artifact-lifecycle-DzPpBYvK.mjs +0 -30
- package/dist/budget-f7516Zk0.mjs +0 -4106
- package/dist/build-facts-DcLv2HSd.d.mts +0 -111
- package/dist/cancellation-C_22VQTH.mjs +0 -24
- package/dist/client-qQAaXSUs.mjs +0 -1771
- package/dist/config-BYDxlMY3.mjs +0 -562
- package/dist/device-DuiPJQSn.mjs +0 -290
- package/dist/device-lease-BX1sJQ2E.mjs +0 -1224
- package/dist/device-remote-xRT0Vmo9.mjs +0 -1272
- package/dist/eas-session-ledger-Cm0Gwq2F.mjs +0 -207
- package/dist/exec-DqKo9GKJ.mjs +0 -268
- package/dist/git-DDfFzkMm.mjs +0 -45
- package/dist/launch-verify-B6Q8hZP-.mjs +0 -428
- package/dist/logs-BGrEUaEs.mjs +0 -383
- package/dist/macos-Ch5VJmcS.mjs +0 -584
- package/dist/metro-gateway-CX9Xlkq2.mjs +0 -103
- package/dist/miss-reason-mKzZ4VvN.mjs +0 -238
- package/dist/native-android-D5qc3-_v.mjs +0 -226
- package/dist/native-gradle-inputs-BsLRrl7u.mjs +0 -349
- package/dist/ndjson-Du3j0AQ9.d.mts +0 -17
- package/dist/plan-C4TjdPsR.mjs +0 -260
- package/dist/prebuild-DYbucPXy.mjs +0 -212
- package/dist/preview-78a9kR_-.mjs +0 -1011
- package/dist/react-native-build-CtCccJtb.mjs +0 -239
- package/dist/react-native-doctor-CfRnFfjs.mjs +0 -78
- package/dist/remote-cache-OyOyVIS3.mjs +0 -526
- package/dist/result-CaJg5Iat.mjs +0 -186
- package/dist/server-expo-Bigriskl.mjs +0 -2
- package/dist/settings-BORNaaCO.mjs +0 -402
- package/dist/settings-vk3mJGSm.d.mts +0 -13
- package/dist/spawn-claims-DVS5RkMS.mjs +0 -72
- package/dist/stage-KNTQopqv.mjs +0 -157
- package/dist/start-BWqzODpb.mjs +0 -1116
- package/dist/stim-desktop-BzBN2Em2.mjs +0 -63
- package/dist/swiftpm-macos-DRNVJWlb.mjs +0 -119
- package/dist/tailnet-Dh-qiYzG.mjs +0 -265
- package/dist/toolchain-BFkAcstd.mjs +0 -2
- package/dist/toolchain-DxSsNssu.mjs +0 -1657
- package/dist/trigger-9_USgmxz.mjs +0 -2
- package/dist/web-Dq-i3wzJ.mjs +0 -2
- package/dist/worktree-DpLdCHga.mjs +0 -2
- package/dist/{api-run.d.mts → doctor-fingerprint.d.mts} +0 -0
- package/dist/{errors-DzkMYh8Q.mjs → errors-ccaPc4ox.mjs} +2 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { f as throwIfCancelled } from "./operation-exec-BW0em61G.mjs";
|
|
2
|
+
import { c as call, l as connectHost } from "./hosted-client-DZAPrcro.mjs";
|
|
3
|
+
import { i as requestHostedMetro } from "./metro-gateway-CKZqKqx7.mjs";
|
|
4
|
+
import { n as prepareHostedNative, r as stopHostedNative, t as placeHostedNative } from "./hosted-native-BdzE668-.mjs";
|
|
4
5
|
//#region src/device-host/hosted-android.ts
|
|
5
6
|
async function prepareHostedAndroid(machine, selectors, recorded, mode) {
|
|
6
7
|
return await prepareHostedNative(machine, selectors, recorded, "android", false, mode);
|
|
@@ -12,13 +13,14 @@ async function placeHostedAndroid(target, options) {
|
|
|
12
13
|
reserved: (placement) => options.reserved(placement)
|
|
13
14
|
});
|
|
14
15
|
}
|
|
15
|
-
async function stopHostedAndroid(root, slot) {
|
|
16
|
-
await stopHostedNative(root, slot, "android");
|
|
16
|
+
async function stopHostedAndroid(root, slot, signal) {
|
|
17
|
+
await stopHostedNative(root, slot, signal, "android");
|
|
17
18
|
}
|
|
18
|
-
async function reopenHostedAndroidMetro(root, placement, clientMetroPort) {
|
|
19
|
-
const host = await connectHost(placement.machine, void 0, true);
|
|
19
|
+
async function reopenHostedAndroidMetro(root, placement, clientMetroPort, signal) {
|
|
20
|
+
const host = await connectHost(placement.machine, void 0, true, signal);
|
|
20
21
|
try {
|
|
21
|
-
const gateway = await requestHostedMetro(root, placement.session, host.credential);
|
|
22
|
+
const gateway = await requestHostedMetro(root, placement.session, host.credential, signal);
|
|
23
|
+
throwIfCancelled(signal, "reload");
|
|
22
24
|
await call(host, "device-host.metro.open", {
|
|
23
25
|
session: placement.session,
|
|
24
26
|
clientMetroPort,
|
|
@@ -1,19 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { t as BuildConnection
|
|
1
|
+
import { rt as resolveEndpoint } from "./config-DlrsduwG.mjs";
|
|
2
|
+
import { f as throwIfCancelled, u as cancellableSleep } from "./operation-exec-BW0em61G.mjs";
|
|
3
|
+
import { t as BuildConnection } from "./client-OyRoEuSr.mjs";
|
|
4
|
+
import { u as configuredMachines } from "./selection-DSMbWEX2.mjs";
|
|
5
|
+
import { createHash } from "node:crypto";
|
|
4
6
|
import { lstatSync, readFileSync, readdirSync, readlinkSync } from "node:fs";
|
|
5
7
|
import { join } from "node:path";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
+
import { configDir } from "@stim-cli/core";
|
|
9
|
+
import { DEVICE_HOST_LIMITS, HOSTED_APP_CHUNK_BYTES, HOSTED_PARKED_CANDIDATES, hostedMacosAppSlot, hostedWorkerSettleMs, isJsonObject, readDeviceHostMachines } from "@stim-cli/core/state";
|
|
8
10
|
//#region src/device-host/hosted-client.ts
|
|
9
11
|
const CONNECT_TIMEOUT_MS = 1e4;
|
|
10
12
|
const HOSTED_POLL_MARGIN_MS = 45e3;
|
|
11
13
|
const HOSTED_REQUEST_MARGIN_MS = 5e3;
|
|
12
14
|
const workerBoundMs = (deadlineMs) => deadlineMs + hostedWorkerSettleMs();
|
|
13
|
-
const SESSION_TIMEOUT_MS = hostedWorkerSettleMs() + workerBoundMs(DEVICE_HOST_LIMITS.logsMs) + workerBoundMs(DEVICE_HOST_LIMITS.stopMs) + HOSTED_POLL_MARGIN_MS;
|
|
15
|
+
const SESSION_TIMEOUT_MS = hostedWorkerSettleMs() + workerBoundMs(DEVICE_HOST_LIMITS.logsMs) + 2 * workerBoundMs(DEVICE_HOST_LIMITS.stopMs) + HOSTED_POLL_MARGIN_MS;
|
|
14
16
|
const PREPARE_TIMEOUT_MS = workerBoundMs(DEVICE_HOST_LIMITS.prepareMs) + HOSTED_POLL_MARGIN_MS;
|
|
15
17
|
const INSTALL_TIMEOUT_MS = workerBoundMs(DEVICE_HOST_LIMITS.prepareMs) + HOSTED_POLL_MARGIN_MS;
|
|
16
18
|
const OFFER_TIMEOUT_MS = workerBoundMs(DEVICE_HOST_LIMITS.offerMs) + HOSTED_REQUEST_MARGIN_MS;
|
|
19
|
+
const RESERVE_TIMEOUT_MS = HOSTED_PARKED_CANDIDATES * (workerBoundMs(DEVICE_HOST_LIMITS.offerMs) + workerBoundMs(DEVICE_HOST_LIMITS.stopMs)) + workerBoundMs(DEVICE_HOST_LIMITS.offerMs) + HOSTED_REQUEST_MARGIN_MS;
|
|
17
20
|
const sha256 = (content) => createHash("sha256").update(content).digest("hex");
|
|
18
21
|
function credentialRefusal(message, remedy = "Run stim doctor.") {
|
|
19
22
|
return Object.assign(new Error(message), {
|
|
@@ -32,22 +35,26 @@ function hostingCredential(machine) {
|
|
|
32
35
|
throw credentialRefusal("The hosting credentials are unreadable. Run stim doctor.");
|
|
33
36
|
}
|
|
34
37
|
const credential = credentials.find((each) => each.machine === machine);
|
|
35
|
-
if (!credential) throw credentialRefusal(`This
|
|
38
|
+
if (!credential) throw credentialRefusal(`This machine has not asked ${machine} for hosting access. Run stim doctor --fix.`, "Run stim doctor --fix.");
|
|
36
39
|
if (credential.state !== "approved") {
|
|
37
|
-
const remedy = `A person on ${machine}
|
|
38
|
-
throw credentialRefusal(`${machine} has not confirmed hosting access for this
|
|
40
|
+
const remedy = `A person on ${machine} runs the stim-server setup command stim doctor --fix printed; then run stim doctor.`;
|
|
41
|
+
throw credentialRefusal(`${machine} has not confirmed hosting access for this machine. ${remedy}`, remedy);
|
|
39
42
|
}
|
|
40
43
|
return credential;
|
|
41
44
|
}
|
|
42
|
-
/** Connects only to the
|
|
43
|
-
async function connectHost(machine, timeoutMs = CONNECT_TIMEOUT_MS, strict = false) {
|
|
45
|
+
/** Connects only to the stim-server that proves it holds the approved machine's pinned key, and only for `device-host`. */
|
|
46
|
+
async function connectHost(machine, timeoutMs = CONNECT_TIMEOUT_MS, strict = false, signal) {
|
|
47
|
+
signal?.throwIfAborted();
|
|
44
48
|
const credential = hostingCredential(machine);
|
|
45
|
-
const target = await
|
|
49
|
+
const target = await resolveEndpoint(credential, void 0, signal);
|
|
50
|
+
signal?.throwIfAborted();
|
|
46
51
|
if (typeof target === "string") throw Object.assign(/* @__PURE__ */ new Error(`Stim does not connect to ${machine}: ${target}.`), { code: "STIM_HOSTING_REFUSED" });
|
|
47
|
-
const opened = await BuildConnection.open(target, credential.
|
|
52
|
+
const opened = await BuildConnection.open(target, credential.serverKey, timeoutMs, "device-host", signal).catch((error) => {
|
|
48
53
|
throw Object.assign(new Error(`${machine} is unreachable. Check stim-server and its tailnet serve route on ${machine}.`, { cause: error }), { code: strict ? "STIM_HOSTING_REFUSED" : "closed" });
|
|
49
54
|
});
|
|
50
|
-
if (
|
|
55
|
+
if (signal?.aborted && opened instanceof BuildConnection) opened.close();
|
|
56
|
+
signal?.throwIfAborted();
|
|
57
|
+
if (!(opened instanceof BuildConnection)) throw Object.assign(/* @__PURE__ */ new Error(opened.code === "server-outdated" ? `${machine} runs a stim-server that speaks an older protocol than this Stim. Run stim doctor for the command that updates it there, then retry.` : opened.refused ? `${machine} refused this machine: ${opened.failure.replace(/\.+$/, "")}. Run stim doctor.` : `${machine} is unreachable: ${opened.failure}. Check stim-server and its tailnet serve route on ${machine}.`), {
|
|
51
58
|
code: strict ? "STIM_HOSTING_REFUSED" : opened.refused ? "STIM_HOSTING_REFUSED" : opened.code ?? "closed",
|
|
52
59
|
hostCode: opened.code
|
|
53
60
|
});
|
|
@@ -63,8 +70,8 @@ function requireHostedAppMode(host, platform, mode) {
|
|
|
63
70
|
}
|
|
64
71
|
const gatewaySecrets = /* @__PURE__ */ new WeakMap();
|
|
65
72
|
function redactHostText(host, message) {
|
|
66
|
-
|
|
67
|
-
return message;
|
|
73
|
+
const secret = gatewaySecrets.get(host);
|
|
74
|
+
return secret ? message.replaceAll(secret, "[redacted]") : message;
|
|
68
75
|
}
|
|
69
76
|
async function call(host, method, params, timeoutMs) {
|
|
70
77
|
if (method === "device-host.metro.open" && isJsonObject(params) && typeof params.secret === "string") gatewaySecrets.set(host, params.secret);
|
|
@@ -92,7 +99,11 @@ async function attach(host, session, timeoutMs, platform = "macos") {
|
|
|
92
99
|
}
|
|
93
100
|
const probeCache = /* @__PURE__ */ new Map();
|
|
94
101
|
function probeHostedSession(placement, { timeoutMs = 3e3, ttlMs = 1e4 } = {}) {
|
|
95
|
-
const key = JSON.stringify([
|
|
102
|
+
const key = JSON.stringify([
|
|
103
|
+
configDir(),
|
|
104
|
+
placement.machine,
|
|
105
|
+
placement.session
|
|
106
|
+
]);
|
|
96
107
|
const cached = probeCache.get(key);
|
|
97
108
|
if (ttlMs > 0 && cached && cached.expiresAt > Date.now()) return cached.promise;
|
|
98
109
|
const promise = probeSession(placement, timeoutMs);
|
|
@@ -145,8 +156,12 @@ async function settle(host, session, passing, timeoutMs, platform = "macos", sig
|
|
|
145
156
|
}
|
|
146
157
|
return session;
|
|
147
158
|
}
|
|
159
|
+
const reason = (session) => session.notice ? `: ${session.notice.replace(/\.+$/, "")}` : "";
|
|
148
160
|
function unknownSession(host, session) {
|
|
149
|
-
return /* @__PURE__ */ new Error(`The hosted session ${session.id} on ${host.machine} is in an unknown state${session
|
|
161
|
+
return /* @__PURE__ */ new Error(`The hosted session ${session.id} on ${host.machine} is in an unknown state${reason(session)}. Run stim stop to reconcile it.`);
|
|
162
|
+
}
|
|
163
|
+
function stoppedSession(host, session) {
|
|
164
|
+
return /* @__PURE__ */ new Error(`The hosted session ${session.id} on ${host.machine} stopped before it was ready${reason(session)}. Retry when the host can take it; it needs no stim stop.`);
|
|
150
165
|
}
|
|
151
166
|
function bundleManifest(bundle) {
|
|
152
167
|
const files = [];
|
|
@@ -207,4 +222,4 @@ async function upload(host, ids, missing, content) {
|
|
|
207
222
|
}
|
|
208
223
|
}
|
|
209
224
|
//#endregion
|
|
210
|
-
export {
|
|
225
|
+
export { unknownSession as _, SESSION_TIMEOUT_MS as a, call as c, hostedSession as d, probeHostedSession as f, stoppedSession as g, sha256 as h, RESERVE_TIMEOUT_MS as i, connectHost as l, settle as m, OFFER_TIMEOUT_MS as n, attach as o, requireHostedAppMode as p, PREPARE_TIMEOUT_MS as r, bundleManifest as s, INSTALL_TIMEOUT_MS as t, heldNoLonger as u, upload as v };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as prepareHostedNative, r as stopHostedNative, t as placeHostedNative } from "./hosted-native-
|
|
1
|
+
import { n as prepareHostedNative, r as stopHostedNative, t as placeHostedNative } from "./hosted-native-BdzE668-.mjs";
|
|
2
2
|
//#region src/device-host/hosted-ios.ts
|
|
3
3
|
async function prepareHostedIos(machine, selectors, recorded, mode) {
|
|
4
4
|
return await prepareHostedNative(machine, selectors, recorded, "ios", false, mode);
|
|
@@ -1,52 +1,84 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { l as phaseLine } from "./command-output-
|
|
5
|
-
import {
|
|
6
|
-
import { r as createNdjsonWriter } from "./ndjson-
|
|
7
|
-
import {
|
|
8
|
-
import { s as call } from "./hosted-client-ZEKpS9vw.mjs";
|
|
1
|
+
import { t as getExecutor } from "./exec-DEoAhcze.mjs";
|
|
2
|
+
import { d as workspaceDir, m as workspaceLogsDir$1 } from "./paths-DQtTgsBf.mjs";
|
|
3
|
+
import { B as deviceSlotFileKey, et as parseMachine$1, q as validateDeviceSlot } from "./config-DlrsduwG.mjs";
|
|
4
|
+
import { l as phaseLine } from "./command-output-gwpm28fu.mjs";
|
|
5
|
+
import { n as macosDir } from "./state-08I3hw3_.mjs";
|
|
6
|
+
import { r as createNdjsonWriter } from "./ndjson-CgE_o3Dl.mjs";
|
|
7
|
+
import { c as call } from "./hosted-client-DZAPrcro.mjs";
|
|
9
8
|
import { mkdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
10
9
|
import { dirname, join } from "node:path";
|
|
10
|
+
import { LOG_ROTATE_BYTES, ambientWrite, withDirLockAsync } from "@stim-cli/core";
|
|
11
11
|
import { isJsonObject, parseHostedAgentGrant, parseHostedLogsCursor } from "@stim-cli/core/state";
|
|
12
|
-
import {
|
|
12
|
+
import { loadAgentDriverModule } from "@stim-cli/agent-driver";
|
|
13
|
+
//#region src/device-host/agent-drivers.ts
|
|
14
|
+
const DRIVERS = { "agent-device": {
|
|
15
|
+
load: () => import("@stim-cli/agent-driver-agent-device"),
|
|
16
|
+
configFile: "agent-device-remote.json"
|
|
17
|
+
} };
|
|
18
|
+
function registered(name) {
|
|
19
|
+
return Object.hasOwn(DRIVERS, name);
|
|
20
|
+
}
|
|
21
|
+
/** The client side of a first-party driver, or a reason it is unavailable to this Stim. */
|
|
22
|
+
async function agentDriverClient(name) {
|
|
23
|
+
if (!registered(name)) return { unavailable: `this Stim has no ${name} driver` };
|
|
24
|
+
const { load, configFile } = DRIVERS[name];
|
|
25
|
+
const loaded = await loadAgentDriverModule(name, load);
|
|
26
|
+
if ("unavailable" in loaded) return loaded;
|
|
27
|
+
const { client } = loaded.module;
|
|
28
|
+
if (!client) return { unavailable: `the ${name} driver has no client` };
|
|
29
|
+
if (client.configFile !== configFile) return { unavailable: `the ${name} driver writes ${client.configFile}, not ${configFile}` };
|
|
30
|
+
return { client };
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The config file names every first-party driver's client writes beside a placement. They are listed here rather
|
|
34
|
+
* than read from the drivers, so access is removed even when a driver package does not load.
|
|
35
|
+
*/
|
|
36
|
+
function agentClientFiles() {
|
|
37
|
+
return Object.values(DRIVERS).map((driver) => driver.configFile);
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
13
40
|
//#region src/device-host/hosted-agent.ts
|
|
14
|
-
|
|
41
|
+
/** Removes every driver's client file beside `file`, the placement's agent-device config path. */
|
|
42
|
+
async function removeAgentAccess(file, keep) {
|
|
43
|
+
for (const name of agentClientFiles()) {
|
|
44
|
+
const path = join(dirname(file), name);
|
|
45
|
+
if (path !== keep) rmSync(path, { force: true });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async function agentAccess(file, credential, grant, note, platform = "macos") {
|
|
15
49
|
const parsed = grant === void 0 ? null : parseHostedAgentGrant(grant);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
50
|
+
const issued = parsed && "token" in parsed ? parsed : null;
|
|
51
|
+
const loaded = issued ? await agentDriverClient(issued.driver) : null;
|
|
52
|
+
if (grant !== void 0 && !parsed || loaded && "unavailable" in loaded) note(`${credential.machine} offered agent control this Stim does not support.`);
|
|
53
|
+
const port = parseMachine$1(credential.machine)?.port ?? 443;
|
|
54
|
+
const client = loaded && "client" in loaded ? loaded.client : null;
|
|
55
|
+
const target = client ? join(dirname(file), client.configFile) : file;
|
|
56
|
+
const access = client && issued ? client.access({
|
|
57
|
+
grant: issued,
|
|
58
|
+
baseUrl: `https://${credential.address}${port === 443 ? "" : `:${port}`}${issued.path}`,
|
|
59
|
+
file: target,
|
|
60
|
+
platform
|
|
61
|
+
}) : null;
|
|
62
|
+
if (!issued || !access) {
|
|
63
|
+
await removeAgentAccess(file);
|
|
19
64
|
return {
|
|
20
65
|
driver: "none",
|
|
21
66
|
setting: "hosting.agentDriver"
|
|
22
67
|
};
|
|
23
68
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
daemonAuthToken: parsed.token,
|
|
28
|
-
tenant: parsed.lease.tenant,
|
|
29
|
-
sessionIsolation: "tenant",
|
|
30
|
-
runId: parsed.lease.runId,
|
|
31
|
-
...platform === "macos" ? { leaseId: parsed.scope } : {},
|
|
32
|
-
leaseBackend: platform === "macos" ? "macos-app" : `${platform}-instance`,
|
|
33
|
-
leaseProvider: "proxy",
|
|
34
|
-
clientId: parsed.lease.clientId,
|
|
35
|
-
deviceKey: parsed.lease.deviceKey,
|
|
36
|
-
platform
|
|
37
|
-
};
|
|
38
|
-
mkdirSync(dirname(file), { recursive: true });
|
|
39
|
-
const tmp = `${file}.${process.pid}.tmp`;
|
|
69
|
+
await removeAgentAccess(file, target);
|
|
70
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
71
|
+
const tmp = `${target}.${process.pid}.tmp`;
|
|
40
72
|
try {
|
|
41
|
-
writeFileSync(tmp,
|
|
42
|
-
renameSync(tmp,
|
|
73
|
+
writeFileSync(tmp, access.config, { mode: 384 });
|
|
74
|
+
renameSync(tmp, target);
|
|
43
75
|
} finally {
|
|
44
76
|
rmSync(tmp, { force: true });
|
|
45
77
|
}
|
|
46
78
|
return {
|
|
47
|
-
driver:
|
|
48
|
-
remoteConfig:
|
|
49
|
-
command:
|
|
79
|
+
driver: issued.driver,
|
|
80
|
+
remoteConfig: target,
|
|
81
|
+
command: access.command
|
|
50
82
|
};
|
|
51
83
|
}
|
|
52
84
|
//#endregion
|
|
@@ -59,7 +91,7 @@ function canonical(path) {
|
|
|
59
91
|
}
|
|
60
92
|
}
|
|
61
93
|
function report(message) {
|
|
62
|
-
|
|
94
|
+
ambientWrite("stderr", `${phaseLine("device", message.replace(/\s+/g, " "))}\n`);
|
|
63
95
|
}
|
|
64
96
|
function closeAgentConnection(remoteConfig) {
|
|
65
97
|
const exec = getExecutor();
|
|
@@ -118,10 +150,10 @@ function readCursor(root, session, target) {
|
|
|
118
150
|
} catch {}
|
|
119
151
|
}
|
|
120
152
|
const sameCursor = (a, b) => JSON.stringify(Object.entries(a ?? {}).toSorted()) === JSON.stringify(Object.entries(b ?? {}).toSorted());
|
|
121
|
-
function commitPage(root, session, before, records, cursor, target) {
|
|
153
|
+
async function commitPage(root, session, before, records, cursor, target) {
|
|
122
154
|
if (!records.length && sameCursor(before, cursor)) return;
|
|
123
155
|
const directory = logsStateDir(root, target);
|
|
124
|
-
|
|
156
|
+
await withDirLockAsync(join(directory, "host-logs.lock"), () => {
|
|
125
157
|
if (!sameCursor(readCursor(root, session, target), before)) return;
|
|
126
158
|
if (records.length) {
|
|
127
159
|
const writer = createNdjsonWriter(hostLogFile(root, target), { maxBytes: LOG_ROTATE_BYTES });
|
|
@@ -149,14 +181,15 @@ function commitPage(root, session, before, records, cursor, target) {
|
|
|
149
181
|
}
|
|
150
182
|
}, { ensureParent: () => mkdirSync(directory, { recursive: true }) });
|
|
151
183
|
}
|
|
152
|
-
async function pullHostedMacosLogs(root, placement, host, target = MACOS, maxPages = MAX_PAGES, final = false) {
|
|
184
|
+
async function pullHostedMacosLogs(root, placement, host, target = MACOS, maxPages = MAX_PAGES, final = false, signal) {
|
|
153
185
|
const deadline = Date.now() + (final ? 3e4 : 12e4);
|
|
154
186
|
let checkpoint;
|
|
155
187
|
let progressAt = 0;
|
|
156
188
|
for (let page = 0; page < maxPages && Date.now() < deadline; page++) {
|
|
189
|
+
signal?.throwIfAborted();
|
|
157
190
|
const before = readCursor(root, placement.session, target);
|
|
158
191
|
if (final && Date.now() >= progressAt) {
|
|
159
|
-
|
|
192
|
+
ambientWrite("stderr", `Copying final native logs from ${host.machine} (page ${page + 1})\n`);
|
|
160
193
|
progressAt = Date.now() + 5e3;
|
|
161
194
|
}
|
|
162
195
|
const result = await call(host, "device-host.logs.query", {
|
|
@@ -165,7 +198,8 @@ async function pullHostedMacosLogs(root, placement, host, target = MACOS, maxPag
|
|
|
165
198
|
}, Math.max(1, Math.min(2e4, deadline - Date.now())));
|
|
166
199
|
const cursor = isJsonObject(result) ? parseHostedLogsCursor(result.cursor) : null;
|
|
167
200
|
if (!isJsonObject(result) || !cursor || !Array.isArray(result.records) || !result.records.every(isJsonObject) || typeof result.more !== "boolean") throw new Error(`${host.machine} answered device-host.logs.query with an unexpected result.`);
|
|
168
|
-
|
|
201
|
+
signal?.throwIfAborted();
|
|
202
|
+
await commitPage(root, placement.session, before, result.records, cursor, target);
|
|
169
203
|
if (!result.more) return;
|
|
170
204
|
const nextCheckpoint = typeof result.checkpoint === "number" ? result.checkpoint : void 0;
|
|
171
205
|
if (sameCursor(cursor, before) && nextCheckpoint === checkpoint) {
|
|
@@ -176,12 +210,12 @@ async function pullHostedMacosLogs(root, placement, host, target = MACOS, maxPag
|
|
|
176
210
|
}
|
|
177
211
|
if (target.platform !== "macos") throw new Error(final ? "Final native log copy reached its time or page bound; the host keeps collected logs after stop." : "Hosted native logs still have unread pages; run stim logs again.");
|
|
178
212
|
}
|
|
179
|
-
async function pullHostedNativeLogs(root, slot, placement, host, final = false, platform = "ios") {
|
|
213
|
+
async function pullHostedNativeLogs(root, slot, placement, host, final = false, platform = "ios", signal) {
|
|
180
214
|
if (!host.connection.supports(platform === "ios" ? "hosted-ios-data" : "hosted-android-data")) throw new Error(`${host.machine} needs a newer stim-server to collect hosted ${platform === "ios" ? "iOS" : "Android"} native logs.`);
|
|
181
215
|
await pullHostedMacosLogs(root, placement, host, {
|
|
182
216
|
platform,
|
|
183
217
|
slot
|
|
184
|
-
}, final ? 1024 : MAX_PAGES, final);
|
|
218
|
+
}, final ? 1024 : MAX_PAGES, final, signal);
|
|
185
219
|
}
|
|
186
220
|
//#endregion
|
|
187
|
-
export { agentAccess as i, pullHostedNativeLogs as n, closeAgentConnection as r, pullHostedMacosLogs as t };
|
|
221
|
+
export { removeAgentAccess as a, agentAccess as i, pullHostedNativeLogs as n, closeAgentConnection as r, pullHostedMacosLogs as t };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { n as macosDir } from "./state-
|
|
5
|
-
import {
|
|
6
|
-
import { i as
|
|
7
|
-
import {
|
|
1
|
+
import { a as removeAgentAccess, i as agentAccess, r as closeAgentConnection, t as pullHostedMacosLogs } from "./hosted-logs-FIRx9X2f.mjs";
|
|
2
|
+
import { l as phaseLine } from "./command-output-gwpm28fu.mjs";
|
|
3
|
+
import { u as cancellableSleep } from "./operation-exec-BW0em61G.mjs";
|
|
4
|
+
import { n as macosDir } from "./state-08I3hw3_.mjs";
|
|
5
|
+
import { d as runCancellationSignal } from "./native-run-NwUuxbkg.mjs";
|
|
6
|
+
import { _ as unknownSession, a as SESSION_TIMEOUT_MS, c as call, d as hostedSession, g as stoppedSession, h as sha256, i as RESERVE_TIMEOUT_MS, l as connectHost, m as settle, o as attach, r as PREPARE_TIMEOUT_MS, s as bundleManifest, t as INSTALL_TIMEOUT_MS, u as heldNoLonger, v as upload } from "./hosted-client-DZAPrcro.mjs";
|
|
7
|
+
import { randomUUID } from "node:crypto";
|
|
8
8
|
import { join } from "node:path";
|
|
9
|
+
import { ambientContext, ambientWrite } from "@stim-cli/core";
|
|
9
10
|
import { hostedMacosBundleId, parseHostedMacosDevice, validHostedAppArguments } from "@stim-cli/core/state";
|
|
10
|
-
import { randomUUID } from "node:crypto";
|
|
11
11
|
//#region src/device-host/hosted-macos.ts
|
|
12
12
|
const HANDOFF_TIMEOUT_MS = 3e5;
|
|
13
13
|
const agentRemoteConfig = (root) => join(macosDir(root), "agent-device-remote.json");
|
|
@@ -20,8 +20,8 @@ async function placeHostedMacos(host, { root, bundle, bundleId, handoff, argumen
|
|
|
20
20
|
let session = null;
|
|
21
21
|
if (recorded) {
|
|
22
22
|
try {
|
|
23
|
-
session = await settle(host, await attach(host, recorded.session), ["preparing"], PREPARE_TIMEOUT_MS, "macos", runCancellationSignal());
|
|
24
|
-
session = await settle(host, session, ["stopping"], SESSION_TIMEOUT_MS, "macos", runCancellationSignal());
|
|
23
|
+
session = await settle(host, await attach(host, recorded.session), ["preparing"], PREPARE_TIMEOUT_MS, "macos", runCancellationSignal(ambientContext()));
|
|
24
|
+
session = await settle(host, session, ["stopping"], SESSION_TIMEOUT_MS, "macos", runCancellationSignal(ambientContext()));
|
|
25
25
|
} catch (error) {
|
|
26
26
|
if (!heldNoLonger(error)) throw error;
|
|
27
27
|
}
|
|
@@ -35,7 +35,7 @@ async function placeHostedMacos(host, { root, bundle, bundleId, handoff, argumen
|
|
|
35
35
|
slot: "default",
|
|
36
36
|
attempt: randomUUID(),
|
|
37
37
|
platform: "macos"
|
|
38
|
-
}));
|
|
38
|
+
}, RESERVE_TIMEOUT_MS));
|
|
39
39
|
}
|
|
40
40
|
const appSlot = session.appSlot;
|
|
41
41
|
if (appSlot === void 0) throw new Error(`${host.machine} reserved a session without a macOS app slot.`);
|
|
@@ -52,8 +52,9 @@ async function placeHostedMacos(host, { root, bundle, bundleId, handoff, argumen
|
|
|
52
52
|
}
|
|
53
53
|
};
|
|
54
54
|
reserved(placement);
|
|
55
|
-
session = await settle(host, session, ["preparing"], PREPARE_TIMEOUT_MS, "macos", runCancellationSignal());
|
|
55
|
+
session = await settle(host, session, ["preparing"], PREPARE_TIMEOUT_MS, "macos", runCancellationSignal(ambientContext()));
|
|
56
56
|
if (session.state === "unknown") throw unknownSession(host, session);
|
|
57
|
+
if (session.state === "stopped") throw stoppedSession(host, session);
|
|
57
58
|
if (session.state !== "ready") throw new Error(`The hosted session ${session.id} on ${host.machine} is ${session.state}.`);
|
|
58
59
|
const device = parseHostedMacosDevice(session.device);
|
|
59
60
|
if (!device || device.appSlot !== appSlot) throw new Error(`${host.machine} reported a ready session without its reserved macOS app slot.`);
|
|
@@ -77,7 +78,7 @@ async function placeHostedMacos(host, { root, bundle, bundleId, handoff, argumen
|
|
|
77
78
|
note(`Delivering ${files.length} files to ${host.machine} (macOS ${device.macosVersion}, ${device.architecture})`);
|
|
78
79
|
await upload(host, ids, (await call(host, "device-host.app.offer", offer)).missing, content);
|
|
79
80
|
let missing = (await call(host, "device-host.app.offer", offer)).missing;
|
|
80
|
-
if (handoff && handoff.
|
|
81
|
+
if (handoff && handoff.serverKey === host.credential.serverKey && Array.isArray(missing) && missing.length) {
|
|
81
82
|
try {
|
|
82
83
|
const taken = await call(host, "device-host.app.handoff", {
|
|
83
84
|
...ids,
|
|
@@ -99,7 +100,10 @@ async function placeHostedMacos(host, { root, bundle, bundleId, handoff, argumen
|
|
|
99
100
|
while (delivery.state !== "installed") {
|
|
100
101
|
if (delivery.state === "unknown") throw new Error(`${host.machine} could not install or launch the app${typeof delivery.notice === "string" ? `: ${delivery.notice}` : ""}.`);
|
|
101
102
|
if (Date.now() > deadline) throw new Error(`${host.machine} did not finish installing the app.`);
|
|
102
|
-
await cancellableSleep(500
|
|
103
|
+
await cancellableSleep(500, {
|
|
104
|
+
signal: runCancellationSignal(ambientContext()),
|
|
105
|
+
what: "hosted app installation"
|
|
106
|
+
});
|
|
103
107
|
delivery = await call(host, "device-host.app.attach", ids);
|
|
104
108
|
}
|
|
105
109
|
const appliedArguments = validHostedAppArguments(delivery.arguments) ? delivery.arguments : [];
|
|
@@ -108,31 +112,40 @@ async function placeHostedMacos(host, { root, bundle, bundleId, handoff, argumen
|
|
|
108
112
|
return {
|
|
109
113
|
placement: {
|
|
110
114
|
...placement,
|
|
111
|
-
agent: agentAccess(agentRemoteConfig(root), host.credential, delivery.agent, note)
|
|
115
|
+
agent: await agentAccess(agentRemoteConfig(root), host.credential, delivery.agent, note)
|
|
112
116
|
},
|
|
113
117
|
launched: delivery.launched === true ? true : "unverified",
|
|
114
118
|
arguments: appliedArguments
|
|
115
119
|
};
|
|
116
120
|
}
|
|
117
121
|
/** Stops a recorded hosted session and waits until the host confirms it stopped; anything else is a failure. */
|
|
118
|
-
async function stopHostedMacos(root, placement) {
|
|
122
|
+
async function stopHostedMacos(root, placement, signal) {
|
|
123
|
+
signal?.throwIfAborted();
|
|
119
124
|
if (placement.agent.driver === "agent-device") closeAgentConnection(placement.agent.remoteConfig);
|
|
120
|
-
|
|
125
|
+
let host;
|
|
126
|
+
const cancel = () => host?.connection.close();
|
|
127
|
+
signal?.addEventListener("abort", cancel, { once: true });
|
|
121
128
|
try {
|
|
129
|
+
host = await connectHost(placement.machine, void 0, false, signal);
|
|
122
130
|
try {
|
|
123
131
|
let session = hostedSession(host, await call(host, "device-host.stop", { session: placement.session }));
|
|
124
|
-
session = await settle(host, session, ["stopping"], SESSION_TIMEOUT_MS);
|
|
132
|
+
session = await settle(host, session, ["stopping"], SESSION_TIMEOUT_MS, "macos", signal);
|
|
133
|
+
signal?.throwIfAborted();
|
|
125
134
|
if (session.state !== "stopped") throw unknownSession(host, session);
|
|
126
|
-
await pullHostedMacosLogs(root, placement, host).catch((error) => {
|
|
127
|
-
|
|
135
|
+
await pullHostedMacosLogs(root, placement, host, void 0, void 0, false, signal).catch((error) => {
|
|
136
|
+
signal?.throwIfAborted();
|
|
137
|
+
ambientWrite("stderr", `${phaseLine("device", `Could not copy the final logs from ${placement.machine}: ${error.message}`)}\n`);
|
|
128
138
|
});
|
|
129
139
|
} catch (error) {
|
|
140
|
+
signal?.throwIfAborted();
|
|
130
141
|
if (!heldNoLonger(error)) throw error;
|
|
131
142
|
}
|
|
132
143
|
} finally {
|
|
133
|
-
|
|
144
|
+
signal?.removeEventListener("abort", cancel);
|
|
145
|
+
host?.connection.close();
|
|
134
146
|
}
|
|
135
|
-
|
|
147
|
+
signal?.throwIfAborted();
|
|
148
|
+
await removeAgentAccess(agentRemoteConfig(root));
|
|
136
149
|
}
|
|
137
150
|
//#endregion
|
|
138
151
|
export { stopHostedMacos as n, placeHostedMacos as t };
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { a as
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
1
|
+
import { d as workspaceDir } from "./paths-DQtTgsBf.mjs";
|
|
2
|
+
import { a as removeAgentAccess, i as agentAccess, n as pullHostedNativeLogs, r as closeAgentConnection } from "./hosted-logs-FIRx9X2f.mjs";
|
|
3
|
+
import { u as cancellableSleep } from "./operation-exec-BW0em61G.mjs";
|
|
4
|
+
import { l as withWorkspaceStateLockAsync, r as readWorkspaceState$1 } from "./workspace-state-U08dEzhG.mjs";
|
|
5
|
+
import { d as runCancellationSignal } from "./native-run-NwUuxbkg.mjs";
|
|
6
|
+
import { _ as unknownSession, a as SESSION_TIMEOUT_MS, c as call, d as hostedSession, g as stoppedSession, h as sha256, i as RESERVE_TIMEOUT_MS, l as connectHost, m as settle, n as OFFER_TIMEOUT_MS, o as attach, p as requireHostedAppMode, r as PREPARE_TIMEOUT_MS, s as bundleManifest, t as INSTALL_TIMEOUT_MS, u as heldNoLonger, v as upload } from "./hosted-client-DZAPrcro.mjs";
|
|
7
|
+
import { a as requireHostedMetro, i as requestHostedMetro, n as closeHostedMetro } from "./metro-gateway-CKZqKqx7.mjs";
|
|
8
|
+
import { s as writeHostedNative } from "./ios-state-Dtw5K2aI.mjs";
|
|
9
|
+
import { randomUUID } from "node:crypto";
|
|
10
|
+
import { readFileSync } from "node:fs";
|
|
9
11
|
import { join } from "node:path";
|
|
12
|
+
import { ambientContext, ambientWrite } from "@stim-cli/core";
|
|
10
13
|
import { hostedNativeRecords, isJsonObject, parseHostedAndroidDevice, parseHostedChoice, parseHostedDevice, parseHostedNativeOffer, parseHostedNativePlacement, requireAutomaticMachine, unreadableHostedNative } from "@stim-cli/core/state";
|
|
11
|
-
import { randomUUID } from "node:crypto";
|
|
12
14
|
//#region src/device-host/hosted-native.ts
|
|
13
15
|
function hostingRefusal(machine, error) {
|
|
14
16
|
return Object.assign(/* @__PURE__ */ new Error(`${machine}: ${error instanceof Error ? error.message : String(error)}`), {
|
|
@@ -26,8 +28,8 @@ async function prepareHostedNative(machine, selectors, recorded, platform = "ios
|
|
|
26
28
|
if (recorded) {
|
|
27
29
|
let session = null;
|
|
28
30
|
try {
|
|
29
|
-
session = await settle(host, await attach(host, recorded.session, void 0, platform), ["preparing"], PREPARE_TIMEOUT_MS, platform, runCancellationSignal());
|
|
30
|
-
session = await settle(host, session, ["stopping"], SESSION_TIMEOUT_MS, platform, runCancellationSignal());
|
|
31
|
+
session = await settle(host, await attach(host, recorded.session, void 0, platform), ["preparing"], PREPARE_TIMEOUT_MS, platform, runCancellationSignal(ambientContext()));
|
|
32
|
+
session = await settle(host, session, ["stopping"], SESSION_TIMEOUT_MS, platform, runCancellationSignal(ambientContext()));
|
|
31
33
|
} catch (error) {
|
|
32
34
|
if (!heldNoLonger(error)) throw error;
|
|
33
35
|
}
|
|
@@ -73,7 +75,7 @@ async function prepareHostedNative(machine, selectors, recorded, platform = "ios
|
|
|
73
75
|
async function reserveHostedNative(host, target, params, platform) {
|
|
74
76
|
try {
|
|
75
77
|
if (target.selection?.selected === "auto") requireAutomaticMachine("device", host.machine);
|
|
76
|
-
return hostedSession(host, await call(host, "device-host.reserve", params), platform);
|
|
78
|
+
return hostedSession(host, await call(host, "device-host.reserve", params, RESERVE_TIMEOUT_MS), platform);
|
|
77
79
|
} catch (error) {
|
|
78
80
|
if (target.selection?.selected !== "auto") throw error;
|
|
79
81
|
throw Object.assign(/* @__PURE__ */ new Error(`${error instanceof Error ? error.message : String(error)} Retry stim ${platform} --remote auto; the build already targets ${host.machine}'s architecture.`), { remedy: `Retry stim ${platform} --remote auto.` });
|
|
@@ -111,7 +113,8 @@ async function placeHostedNative(target, { root, slot, bundle, handoff, bundleId
|
|
|
111
113
|
}
|
|
112
114
|
};
|
|
113
115
|
reserved(placement);
|
|
114
|
-
session = await settle(host, session, ["preparing"], PREPARE_TIMEOUT_MS, platform, runCancellationSignal());
|
|
116
|
+
session = await settle(host, session, ["preparing"], PREPARE_TIMEOUT_MS, platform, runCancellationSignal(ambientContext()));
|
|
117
|
+
if (session.state === "stopped") throw stoppedSession(host, session);
|
|
115
118
|
if (session.state !== "ready") throw unknownSession(host, session);
|
|
116
119
|
const device = platform === "ios" ? parseHostedDevice(session.device) : parseHostedAndroidDevice(session.device);
|
|
117
120
|
if (!device || device.architecture !== target.choice.architecture || "avdName" in device && "systemImage" in target.choice && (device.systemImage !== target.choice.systemImage || device.deviceProfile !== target.choice.deviceProfile)) throw new Error(platform === "ios" ? "The reserved simulator does not match the offered architecture." : "The reserved emulator does not match the offered architecture or selectors.");
|
|
@@ -164,7 +167,7 @@ async function placeHostedNative(target, { root, slot, bundle, handoff, bundleId
|
|
|
164
167
|
note(`Delivering ${files.length} files to ${host.machine} (${"runtime" in device ? device.runtime : device.systemImage}, ${device.architecture})`);
|
|
165
168
|
await upload(host, ids, (await call(host, "device-host.app.offer", offer)).missing, content);
|
|
166
169
|
let missing = (await call(host, "device-host.app.offer", offer)).missing;
|
|
167
|
-
if (handoff && handoff.
|
|
170
|
+
if (handoff && handoff.serverKey === host.credential.serverKey && Array.isArray(missing) && missing.length) {
|
|
168
171
|
if (!host.connection.supports(platform === "android" ? "hosted-android-data" : "hosted-ios-data")) note(`${host.machine} needs a newer stim-server for ${platform === "ios" ? "iOS" : "Android"} build handoff; uploading the app instead`);
|
|
169
172
|
else try {
|
|
170
173
|
const taken = await call(host, "device-host.app.handoff", {
|
|
@@ -184,7 +187,10 @@ async function placeHostedNative(target, { root, slot, bundle, handoff, bundleId
|
|
|
184
187
|
break;
|
|
185
188
|
} catch (offerError) {
|
|
186
189
|
if (!String(offerError).includes("native operation in progress") || Date.now() >= fallbackDeadline) throw offerError;
|
|
187
|
-
await cancellableSleep(Math.min(500, Math.max(0, fallbackDeadline - Date.now()))
|
|
190
|
+
await cancellableSleep(Math.min(500, Math.max(0, fallbackDeadline - Date.now())), {
|
|
191
|
+
signal: runCancellationSignal(ambientContext()),
|
|
192
|
+
what: "hosted app offer"
|
|
193
|
+
});
|
|
188
194
|
}
|
|
189
195
|
}
|
|
190
196
|
}
|
|
@@ -196,13 +202,16 @@ async function placeHostedNative(target, { root, slot, bundle, handoff, bundleId
|
|
|
196
202
|
while (delivery.state !== "installed") {
|
|
197
203
|
if (delivery.state === "unknown") throw new Error(typeof delivery.notice === "string" ? delivery.notice : "App installation or launch is unknown.");
|
|
198
204
|
if (Date.now() > deadline) throw new Error("App installation did not finish.");
|
|
199
|
-
await cancellableSleep(500
|
|
205
|
+
await cancellableSleep(500, {
|
|
206
|
+
signal: runCancellationSignal(ambientContext()),
|
|
207
|
+
what: "hosted app installation"
|
|
208
|
+
});
|
|
200
209
|
delivery = await call(host, "device-host.app.attach", ids);
|
|
201
210
|
}
|
|
202
211
|
if (typeof delivery.notice === "string") note(delivery.notice);
|
|
203
212
|
placement = {
|
|
204
213
|
...placement,
|
|
205
|
-
agent: agentAccess(platform === "ios" ? iosAgentRemoteConfig(root, slot) : androidAgentRemoteConfig(root, slot), host.credential, host.connection.supports(platform === "ios" ? "hosted-ios-agent" : "hosted-android-agent") ? delivery.agent : void 0, note, platform)
|
|
214
|
+
agent: await agentAccess(platform === "ios" ? iosAgentRemoteConfig(root, slot) : androidAgentRemoteConfig(root, slot), host.credential, host.connection.supports(platform === "ios" ? "hosted-ios-agent" : "hosted-android-agent") ? delivery.agent : void 0, note, platform)
|
|
206
215
|
};
|
|
207
216
|
return {
|
|
208
217
|
placement,
|
|
@@ -214,9 +223,11 @@ async function placeHostedNative(target, { root, slot, bundle, handoff, bundleId
|
|
|
214
223
|
if (platform === "android") host.connection.close();
|
|
215
224
|
}
|
|
216
225
|
}
|
|
217
|
-
async function stopHostedNative(root, slot, platform = "ios") {
|
|
226
|
+
async function stopHostedNative(root, slot, signal, platform = "ios") {
|
|
227
|
+
signal?.throwIfAborted();
|
|
218
228
|
const failures = [];
|
|
219
229
|
for (const [name, record] of Object.entries(hostedNativeRecords(readWorkspaceState$1(root), platform))) {
|
|
230
|
+
signal?.throwIfAborted();
|
|
220
231
|
if (slot !== void 0 && name !== slot) continue;
|
|
221
232
|
const placement = parseHostedNativePlacement(record, platform);
|
|
222
233
|
if (!placement) {
|
|
@@ -225,21 +236,28 @@ async function stopHostedNative(root, slot, platform = "ios") {
|
|
|
225
236
|
}
|
|
226
237
|
if (placement.agent.driver === "agent-device") closeAgentConnection(placement.agent.remoteConfig);
|
|
227
238
|
let host;
|
|
239
|
+
const cancel = () => host?.connection.close();
|
|
240
|
+
signal?.addEventListener("abort", cancel, { once: true });
|
|
228
241
|
try {
|
|
229
|
-
host = await connectHost(placement.machine);
|
|
242
|
+
host = await connectHost(placement.machine, void 0, false, signal);
|
|
230
243
|
try {
|
|
231
|
-
await pullHostedNativeLogs(root, name, placement, host, true, platform);
|
|
244
|
+
await pullHostedNativeLogs(root, name, placement, host, true, platform, signal);
|
|
232
245
|
} catch (error) {
|
|
233
|
-
|
|
246
|
+
signal?.throwIfAborted();
|
|
247
|
+
ambientWrite("stderr", `Could not copy final native logs from ${placement.machine}: ${error.message}\n`);
|
|
234
248
|
}
|
|
235
|
-
|
|
249
|
+
signal?.throwIfAborted();
|
|
250
|
+
const stopped = await settle(host, hostedSession(host, await call(host, "device-host.stop", { session: placement.session }), platform), ["stopping"], SESSION_TIMEOUT_MS, platform, signal);
|
|
251
|
+
signal?.throwIfAborted();
|
|
236
252
|
if (stopped.state !== "stopped") throw unknownSession(host, stopped);
|
|
237
253
|
try {
|
|
238
|
-
await pullHostedNativeLogs(root, name, placement, host, true, platform);
|
|
254
|
+
await pullHostedNativeLogs(root, name, placement, host, true, platform, signal);
|
|
239
255
|
} catch (error) {
|
|
240
|
-
|
|
256
|
+
signal?.throwIfAborted();
|
|
257
|
+
ambientWrite("stderr", `Could not copy the host's final native logs from ${placement.machine}: ${error.message}\n`);
|
|
241
258
|
}
|
|
242
259
|
} catch (error) {
|
|
260
|
+
signal?.throwIfAborted();
|
|
243
261
|
const code = error instanceof Error && "code" in error ? error.code : void 0;
|
|
244
262
|
const hostCode = error instanceof Error && "hostCode" in error ? error.hostCode : code;
|
|
245
263
|
if (hostCode !== "unknown-session" && hostCode !== "forbidden") {
|
|
@@ -248,13 +266,17 @@ async function stopHostedNative(root, slot, platform = "ios") {
|
|
|
248
266
|
continue;
|
|
249
267
|
}
|
|
250
268
|
} finally {
|
|
269
|
+
signal?.removeEventListener("abort", cancel);
|
|
251
270
|
host?.connection.close();
|
|
252
271
|
}
|
|
272
|
+
signal?.throwIfAborted();
|
|
253
273
|
try {
|
|
254
|
-
await closeHostedMetro(root, placement.session);
|
|
255
|
-
|
|
256
|
-
|
|
274
|
+
await closeHostedMetro(root, placement.session, signal);
|
|
275
|
+
signal?.throwIfAborted();
|
|
276
|
+
await removeAgentAccess(platform === "ios" ? iosAgentRemoteConfig(root, name) : androidAgentRemoteConfig(root, name));
|
|
277
|
+
await withWorkspaceStateLockAsync(root, () => writeHostedNative(root, name, null, platform), signal);
|
|
257
278
|
} catch (error) {
|
|
279
|
+
signal?.throwIfAborted();
|
|
258
280
|
failures.push(`${placement.machine}: ${error.message}. The placement is kept; rerun stim stop.`);
|
|
259
281
|
}
|
|
260
282
|
}
|