rnxsim 0.1.313 → 0.1.314
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/LICENSE +11 -10
- package/README.md +5 -0
- package/cli/app-config.ts +65 -0
- package/cli/app-fonts.ts +408 -0
- package/cli/app-project.ts +231 -0
- package/cli/app-splash.ts +185 -0
- package/cli/app-state-reset.ts +24 -0
- package/cli/auth.ts +155 -0
- package/cli/bin.ts +594 -0
- package/cli/bridge-diagnostics.ts +226 -0
- package/cli/bridge-flow-runner.ts +2830 -0
- package/cli/browser-evals.ts +96 -0
- package/cli/commands/agent-wrapper.ts +986 -0
- package/cli/commands/agent.ts +423 -0
- package/cli/commands/app-fonts.ts +98 -0
- package/cli/commands/assert.ts +541 -0
- package/cli/commands/auth.ts +59 -0
- package/cli/commands/camera.ts +266 -0
- package/cli/commands/cleanup.ts +169 -0
- package/cli/commands/compat.ts +87 -0
- package/cli/commands/config.ts +32 -0
- package/cli/commands/control.ts +2142 -0
- package/cli/commands/cpu-profile.ts +269 -0
- package/cli/commands/daemon-mac-app.ts +169 -0
- package/cli/commands/daemon.ts +874 -0
- package/cli/commands/debug.ts +719 -0
- package/cli/commands/desktop.ts +39 -0
- package/cli/commands/detect.ts +197 -0
- package/cli/commands/detox.ts +385 -0
- package/cli/commands/device.ts +133 -0
- package/cli/commands/diagnose.ts +589 -0
- package/cli/commands/electron.ts +95 -0
- package/cli/commands/film.ts +379 -0
- package/cli/commands/flow.ts +1124 -0
- package/cli/commands/inspect/actions.ts +622 -0
- package/cli/commands/inspect/core.ts +2405 -0
- package/cli/commands/inspect/count.ts +17 -0
- package/cli/commands/inspect/describe.ts +192 -0
- package/cli/commands/inspect/env.ts +23 -0
- package/cli/commands/inspect/find.ts +171 -0
- package/cli/commands/inspect/get-layout.ts +39 -0
- package/cli/commands/inspect/keyboard.ts +52 -0
- package/cli/commands/inspect/list.ts +58 -0
- package/cli/commands/inspect/memory.ts +215 -0
- package/cli/commands/inspect/redaction.ts +39 -0
- package/cli/commands/inspect/resolve-target.ts +82 -0
- package/cli/commands/inspect/screens.ts +78 -0
- package/cli/commands/inspect/settle.ts +22 -0
- package/cli/commands/inspect/settling.ts +158 -0
- package/cli/commands/inspect/shared.ts +353 -0
- package/cli/commands/inspect/sleep.ts +14 -0
- package/cli/commands/inspect/tree.ts +32 -0
- package/cli/commands/inspect/url.ts +17 -0
- package/cli/commands/inspect/wait-event.ts +210 -0
- package/cli/commands/inspect/wait-idle.ts +24 -0
- package/cli/commands/inspect/wait-ready.ts +74 -0
- package/cli/commands/inspect/wait-selector.ts +54 -0
- package/cli/commands/inspect/wait.ts +31 -0
- package/cli/commands/inspect.ts +4519 -0
- package/cli/commands/install-desktop.ts +351 -0
- package/cli/commands/login.ts +331 -0
- package/cli/commands/logout.ts +31 -0
- package/cli/commands/maestro-generate.ts +361 -0
- package/cli/commands/maestro.ts +453 -0
- package/cli/commands/mode.ts +57 -0
- package/cli/commands/no-bridge-hint.ts +80 -0
- package/cli/commands/perf.ts +66 -0
- package/cli/commands/permissions.ts +203 -0
- package/cli/commands/profile.ts +108 -0
- package/cli/commands/react.ts +353 -0
- package/cli/commands/record.ts +1434 -0
- package/cli/commands/report-issue.ts +305 -0
- package/cli/commands/reset.ts +85 -0
- package/cli/commands/runtime.ts +351 -0
- package/cli/commands/screenshot-command.ts +106 -0
- package/cli/commands/screenshot-layers.ts +143 -0
- package/cli/commands/screenshot-mode.ts +37 -0
- package/cli/commands/screenshot.ts +488 -0
- package/cli/commands/screenshots-capture.ts +607 -0
- package/cli/commands/screenshots.ts +127 -0
- package/cli/commands/serve.ts +168 -0
- package/cli/commands/setup.ts +545 -0
- package/cli/commands/shell-boolean-mode.ts +81 -0
- package/cli/commands/skills.ts +467 -0
- package/cli/commands/slides.ts +361 -0
- package/cli/commands/state.ts +87 -0
- package/cli/commands/storage.ts +58 -0
- package/cli/commands/telemetry.ts +54 -0
- package/cli/commands/three-mode.ts +763 -0
- package/cli/commands/timeline.ts +122 -0
- package/cli/commands/upgrade.ts +208 -0
- package/cli/commands/upload.ts +1225 -0
- package/cli/commands/version.ts +54 -0
- package/cli/commands/what-happened.ts +327 -0
- package/cli/current-sim.ts +204 -0
- package/cli/desktop-companion.ts +300 -0
- package/cli/drivers/electron.ts +70 -0
- package/cli/drivers/index.ts +20 -0
- package/cli/drivers/playwright-provisioning.ts +180 -0
- package/cli/drivers/playwright.ts +698 -0
- package/cli/drivers/registry.ts +65 -0
- package/cli/drivers/types.ts +102 -0
- package/cli/flow-file.ts +142 -0
- package/cli/flow-live-status.ts +120 -0
- package/cli/flow-session.ts +187 -0
- package/cli/help.ts +80 -0
- package/cli/hidden-runtime-alias.ts +19 -0
- package/cli/hints.ts +216 -0
- package/cli/inspect-notice-state.ts +114 -0
- package/cli/maestro-js.ts +334 -0
- package/cli/open-url.ts +8 -0
- package/cli/parent-pid.ts +204 -0
- package/cli/parse-args.ts +211 -0
- package/cli/prompt.ts +51 -0
- package/cli/recording-access.ts +107 -0
- package/cli/registry.ts +1 -0
- package/cli/resolve-assets.ts +63 -0
- package/cli/run-registry.ts +226 -0
- package/cli/runtime-notes.ts +66 -0
- package/cli/runtime-summary.ts +25 -0
- package/cli/setup-repository.ts +187 -0
- package/cli/telemetry.ts +187 -0
- package/cli/ws-bridge.ts +798 -0
- package/dist-cli/bin.js +5 -5
- package/dist-cli/chunks/{agent-XZ2KTPCU.js → agent-7YBDCYMA.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-JJYYW2WH.js → agent-wrapper-2GHFBHCR.js} +2 -2
- package/dist-cli/chunks/{app-fonts-IXRNQG6B.js → app-fonts-RSNVPQSU.js} +2 -2
- package/dist-cli/chunks/{assert-54T5SK5F.js → assert-XCMX3XJX.js} +2 -2
- package/dist-cli/chunks/{auth-FI5UDI45.js → auth-B442HRAX.js} +2 -2
- package/dist-cli/chunks/{beta-JV6UKADW.js → beta-XJ55JK3M.js} +2 -2
- package/dist-cli/chunks/camera-UGYSSLIK.js +33 -0
- package/dist-cli/chunks/{chunk-3NV2NCNX.js → chunk-277AEQZX.js} +2 -2
- package/dist-cli/chunks/{chunk-2YR5BGA5.js → chunk-2JNSK774.js} +2 -2
- package/dist-cli/chunks/{chunk-RSZWCKNT.js → chunk-32WOTSTR.js} +3 -3
- package/dist-cli/chunks/{chunk-WEXDAC74.js → chunk-3S753SNQ.js} +2 -2
- package/dist-cli/chunks/{chunk-IJO63TDP.js → chunk-46ZOLOYA.js} +2 -2
- package/dist-cli/chunks/{chunk-WUSWBCWA.js → chunk-5L7ELDQL.js} +8 -9
- package/dist-cli/chunks/{chunk-WF3T4SVI.js → chunk-7OOPFSQS.js} +2 -2
- package/dist-cli/chunks/{chunk-TZFFR3SD.js → chunk-7SV3RPRW.js} +2 -2
- package/dist-cli/chunks/{chunk-WWZIXIRD.js → chunk-7ZC35MOU.js} +1 -1
- package/dist-cli/chunks/chunk-AMG5E6CC.js +9 -0
- package/dist-cli/chunks/{chunk-WINYQ44O.js → chunk-APWNH3A4.js} +1 -1
- package/dist-cli/chunks/chunk-B57XUKY3.js +4 -0
- package/dist-cli/chunks/{chunk-YDGQTMQL.js → chunk-C2NL26TD.js} +1 -1
- package/dist-cli/chunks/{chunk-NMF2ZMZQ.js → chunk-D2FNUWAB.js} +4 -4
- package/dist-cli/chunks/{chunk-YIFT42WN.js → chunk-E5T4XSJ3.js} +2 -2
- package/dist-cli/chunks/{chunk-46EUUFJ5.js → chunk-EAC34EQS.js} +1 -1
- package/dist-cli/chunks/{chunk-OVFJFXUD.js → chunk-EG32ML36.js} +2 -2
- package/dist-cli/chunks/{chunk-5YJCOWCH.js → chunk-FXUAC6D5.js} +1 -1
- package/dist-cli/chunks/chunk-GQSL4USA.js +6 -0
- package/dist-cli/chunks/{chunk-VFCMSYZK.js → chunk-HAXW27SS.js} +2 -2
- package/dist-cli/chunks/{chunk-2D2UPBBR.js → chunk-IZAHPAN6.js} +1 -1
- package/dist-cli/chunks/{chunk-7GN3LVWB.js → chunk-J62KM5TB.js} +2 -2
- package/dist-cli/chunks/{chunk-BTWORNNG.js → chunk-JEMCD5E4.js} +1 -1
- package/dist-cli/chunks/{chunk-DCEMHR2Y.js → chunk-JZS3Q37N.js} +2 -2
- package/dist-cli/chunks/{chunk-D4FFVGI5.js → chunk-KR4JON7D.js} +1 -1
- package/dist-cli/chunks/chunk-KWCYKQIQ.js +4 -0
- package/dist-cli/chunks/{chunk-VNQEB4L7.js → chunk-MCWPL644.js} +2 -2
- package/dist-cli/chunks/chunk-MJYK3N2I.js +4 -0
- package/dist-cli/chunks/{chunk-5TEF3ET3.js → chunk-O6TRIZNS.js} +2 -2
- package/dist-cli/chunks/{chunk-QKDWYITG.js → chunk-P7XL2E73.js} +3 -3
- package/dist-cli/chunks/{chunk-BBULZ7CG.js → chunk-PFQTUKQ4.js} +62 -87
- package/dist-cli/chunks/{chunk-GGRX24GF.js → chunk-PG5RZCTN.js} +2 -2
- package/dist-cli/chunks/{chunk-W6K4EFPH.js → chunk-QGRI2Z4M.js} +2 -2
- package/dist-cli/chunks/{chunk-ZMJD5GEC.js → chunk-QLXXE7GE.js} +1 -1
- package/dist-cli/chunks/{chunk-VZXWHRUZ.js → chunk-QOJJJWJE.js} +89 -133
- package/dist-cli/chunks/{chunk-OZSSI4WN.js → chunk-RWZY5427.js} +2 -2
- package/dist-cli/chunks/{chunk-UC6U3MML.js → chunk-RZKU2K3J.js} +2 -2
- package/dist-cli/chunks/{chunk-IJ5CAZZC.js → chunk-SBV4IK4H.js} +1 -1
- package/dist-cli/chunks/{chunk-DZS6WPUI.js → chunk-SGMVFFMK.js} +1 -1
- package/dist-cli/chunks/{chunk-OHAZNXLK.js → chunk-TAX4UT2N.js} +1 -1
- package/dist-cli/chunks/{chunk-5DHC6KHQ.js → chunk-TUOFAWXT.js} +1 -1
- package/dist-cli/chunks/{chunk-GASE6UBA.js → chunk-UHZLOHGP.js} +1 -1
- package/dist-cli/chunks/{chunk-F5ZRSS3C.js → chunk-VC7V76U3.js} +1 -1
- package/dist-cli/chunks/{chunk-RTN5C5RL.js → chunk-VQVMLW4U.js} +1 -1
- package/dist-cli/chunks/{chunk-WMIIKMGK.js → chunk-VUKKYPZN.js} +2 -2
- package/dist-cli/chunks/{chunk-5TPRP5QT.js → chunk-WGGRJDRE.js} +1 -1
- package/dist-cli/chunks/chunk-X6H76EKP.js +15 -0
- package/dist-cli/chunks/chunk-XLZ5FNRT.js +27 -0
- package/dist-cli/chunks/{chunk-HI5TFJWN.js → chunk-XULEACM4.js} +2 -2
- package/dist-cli/chunks/{chunk-MJRLLB4R.js → chunk-YFSDM7AX.js} +4 -4
- package/dist-cli/chunks/chunk-YWI3UEVX.js +5 -0
- package/dist-cli/chunks/{chunk-XEVZYVIW.js → chunk-ZBSJO4NB.js} +10 -9
- package/dist-cli/chunks/{cleanup-P27PA6JI.js → cleanup-EYLGCA6Z.js} +2 -2
- package/dist-cli/chunks/cli-version-LL2UGIHE.js +4 -0
- package/dist-cli/chunks/{compat-ZD65FED3.js → compat-TLJYHB4E.js} +2 -2
- package/dist-cli/chunks/{config-XMJRNM2A.js → config-4JWUOEXK.js} +2 -2
- package/dist-cli/chunks/{control-KMIQT3QP.js → control-HPAOYF4N.js} +2 -2
- package/dist-cli/chunks/daemon-OYLASXLE.js +4 -0
- package/dist-cli/chunks/{debug-PT4HOP7N.js → debug-4BKXF6KI.js} +5 -5
- package/dist-cli/chunks/{desktop-S3FG72AK.js → desktop-ZQ6ZD2S6.js} +3 -3
- package/dist-cli/chunks/{detox-B3D4IFCN.js → detox-WNPASSS3.js} +2 -2
- package/dist-cli/chunks/{device-XBNDSB2R.js → device-BXLXVG3V.js} +2 -2
- package/dist-cli/chunks/{diagnose-HMQXJE5N.js → diagnose-3QX7W5RW.js} +2 -2
- package/dist-cli/chunks/{disk-cleanup-BLCZ5BSZ.js → disk-cleanup-KSWKI7WB.js} +2 -2
- package/dist-cli/chunks/drivers-EPIEFF7P.js +4 -0
- package/dist-cli/chunks/{film-BJGTBYZB.js → film-GDMR33VO.js} +3 -3
- package/dist-cli/chunks/flow-NKMPBYCJ.js +4 -0
- package/dist-cli/chunks/help-OGCBHOKA.js +4 -0
- package/dist-cli/chunks/{hidden-runtime-alias-ANOYADHM.js → hidden-runtime-alias-S2GTDX3T.js} +2 -2
- package/dist-cli/chunks/home-paths-QRCDLTTV.js +4 -0
- package/dist-cli/chunks/inspect-FUYMOZPY.js +4 -0
- package/dist-cli/chunks/install-desktop-FR6YKW7Y.js +4 -0
- package/dist-cli/chunks/{login-FJ737MWG.js → login-IJAPUZHI.js} +4 -4
- package/dist-cli/chunks/{logout-ZCNMMHMY.js → logout-QMXDFU2X.js} +2 -2
- package/dist-cli/chunks/{maestro-SZTNKLDF.js → maestro-ZXU3YCVX.js} +3 -3
- package/dist-cli/chunks/{maestro-generate-DCFAIZ4H.js → maestro-generate-PYB5QY7K.js} +3 -3
- package/dist-cli/chunks/{mode-GRMQCRXR.js → mode-WGUCL5FZ.js} +2 -2
- package/dist-cli/chunks/{optional-demo-registry-W36EWFFB.js → optional-demo-registry-WH2O6H36.js} +2 -2
- package/dist-cli/chunks/{perf-QYBAAUZG.js → perf-TOD3UFAH.js} +2 -2
- package/dist-cli/chunks/{permissions-3QCQ6VF4.js → permissions-I5BRJGTB.js} +2 -2
- package/dist-cli/chunks/{record-QPPC2S4E.js → record-ZYL2FYSK.js} +3 -3
- package/dist-cli/chunks/{report-issue-7NMFP4HK.js → report-issue-TAI6DYZO.js} +2 -2
- package/dist-cli/chunks/reset-7YGYKQPQ.js +4 -0
- package/dist-cli/chunks/runtime-B4JO6QRI.js +4 -0
- package/dist-cli/chunks/{screenshot-command-67AECJFB.js → screenshot-command-7ANLODZY.js} +7 -7
- package/dist-cli/chunks/{screenshot-layers-ASWBYPJL.js → screenshot-layers-A7FYXSVU.js} +3 -3
- package/dist-cli/chunks/{screenshots-capture-PXA3HFQK.js → screenshots-capture-WT2ZY6CB.js} +2 -2
- package/dist-cli/chunks/serve-TG5WKA4V.js +44 -0
- package/dist-cli/chunks/{setup-7DWPMRSB.js → setup-PCWLD22V.js} +2 -2
- package/dist-cli/chunks/{skills-S3Y22TUA.js → skills-27ZHWCQS.js} +2 -2
- package/dist-cli/chunks/state-ZQVY46ZO.js +14 -0
- package/dist-cli/chunks/{storage-XUIMJWAJ.js → storage-OYC57C4X.js} +6 -6
- package/dist-cli/chunks/store-32HSPZHI.js +4 -0
- package/dist-cli/chunks/telemetry-PBJR7XHR.js +4 -0
- package/dist-cli/chunks/{timeline-TMPLQPSP.js → timeline-RAJJFQT6.js} +2 -2
- package/dist-cli/chunks/{upgrade-7HDSIM7K.js → upgrade-OEFNZRIP.js} +2 -2
- package/dist-cli/chunks/upload-LQJITLKK.js +4 -0
- package/dist-cli/chunks/version-NIXTY6PL.js +6 -0
- package/dist-cli/chunks/{web-DG3WBYD3.js → web-XBUTBVGR.js} +2 -2
- package/dist-cli/chunks/{what-happened-XFVUTZR7.js → what-happened-YNHRFUDX.js} +3 -3
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract.cjs +20 -0
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +1 -1
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +67 -28
- package/dist-lib/host/bridge-host.cjs +140 -12
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +2815 -40
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro.cjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +2549 -2061
- package/dist-lib/sdk.mjs +2543 -2061
- package/dist-lib/skills.cjs +480 -280
- package/dist-lib/vite.cjs +1 -1
- package/package.json +8 -2
- package/src/bridge-constants.ts +3 -4
- package/src/bridge-contract.ts +251 -0
- package/src/connect.ts +83 -0
- package/src/disk-cleanup.ts +30 -0
- package/src/home-paths.ts +81 -38
- package/src/host/bridge-host.ts +134 -6
- package/src/index.ts +27 -1
- package/src/sdk.ts +8 -0
- package/src/sim-client.ts +660 -0
- package/dist-cli/chunks/camera-VL73YIKP.js +0 -22
- package/dist-cli/chunks/chunk-4NPPOV2N.js +0 -5
- package/dist-cli/chunks/chunk-FSUYIVJ6.js +0 -9
- package/dist-cli/chunks/chunk-G2WW6L2C.js +0 -23
- package/dist-cli/chunks/chunk-KTHV3RUS.js +0 -26
- package/dist-cli/chunks/chunk-LF2ZVT7O.js +0 -6
- package/dist-cli/chunks/chunk-NFK7T35W.js +0 -4
- package/dist-cli/chunks/chunk-TIVZIMMW.js +0 -4
- package/dist-cli/chunks/cli-version-WWLPBDQ7.js +0 -4
- package/dist-cli/chunks/daemon-G2ME7NLB.js +0 -4
- package/dist-cli/chunks/drivers-LDECZGP2.js +0 -4
- package/dist-cli/chunks/flow-UEQNVTU7.js +0 -4
- package/dist-cli/chunks/help-T5FYSVGB.js +0 -4
- package/dist-cli/chunks/home-paths-GT3LFNOR.js +0 -4
- package/dist-cli/chunks/inspect-ZA6XF5LD.js +0 -4
- package/dist-cli/chunks/install-desktop-TIMUDHPL.js +0 -4
- package/dist-cli/chunks/runtime-XOAXMSTU.js +0 -4
- package/dist-cli/chunks/serve-BI2NBAXG.js +0 -44
- package/dist-cli/chunks/store-JTHEJLAZ.js +0 -4
- package/dist-cli/chunks/telemetry-ZYJGD2DB.js +0 -4
- package/dist-cli/chunks/upload-GMSZPWM6.js +0 -4
- package/dist-cli/chunks/version-HOCHZ37L.js +0 -6
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
// sootsim setup — the single guided machine and repository onboarding flow.
|
|
2
|
+
|
|
3
|
+
import fs from 'node:fs'
|
|
4
|
+
import os from 'node:os'
|
|
5
|
+
import path from 'node:path'
|
|
6
|
+
import {
|
|
7
|
+
COMPAT_RESULT_CAVEAT,
|
|
8
|
+
countScanResults,
|
|
9
|
+
formatDetailedScanLines,
|
|
10
|
+
formatScanCounts,
|
|
11
|
+
scanDeps,
|
|
12
|
+
type ScanResult,
|
|
13
|
+
} from '@sootsim/compat/web'
|
|
14
|
+
import { DEFAULT_SOOTSIM_BRIDGE_PORT } from '../../src/bridge-constants'
|
|
15
|
+
import { getCliVersion } from '../../src/cli-version'
|
|
16
|
+
import {
|
|
17
|
+
isDaemonLockfileFresh,
|
|
18
|
+
readActiveRuntime,
|
|
19
|
+
readDaemonLockfile,
|
|
20
|
+
readPrivacyPreferences,
|
|
21
|
+
runtimeDir,
|
|
22
|
+
writePrivacyPreferences,
|
|
23
|
+
} from '../../src/home-paths'
|
|
24
|
+
import { sootsimRuntime } from '../../src/runtime-delivery'
|
|
25
|
+
import { confirm } from '../prompt'
|
|
26
|
+
import {
|
|
27
|
+
applyRepositorySetup,
|
|
28
|
+
detectPreferredPackageManager,
|
|
29
|
+
findPackageRoot,
|
|
30
|
+
formatRepositoryOperations,
|
|
31
|
+
planRepositorySetup,
|
|
32
|
+
type RepositorySetupPlan,
|
|
33
|
+
} from '../setup-repository'
|
|
34
|
+
import { trackCliEvent } from '../telemetry'
|
|
35
|
+
import { daemonInstall, getDaemonServiceStatus } from './daemon'
|
|
36
|
+
|
|
37
|
+
interface SetupOptions {
|
|
38
|
+
appDir: string
|
|
39
|
+
ci: boolean
|
|
40
|
+
dryRun: boolean
|
|
41
|
+
fromWelcome: boolean
|
|
42
|
+
json: boolean
|
|
43
|
+
yes: boolean
|
|
44
|
+
service: boolean | undefined
|
|
45
|
+
repository: boolean | undefined
|
|
46
|
+
productAnalytics: boolean | undefined
|
|
47
|
+
crashReports: boolean | undefined
|
|
48
|
+
shareCompatibility: boolean
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface MachineSetupStatus {
|
|
52
|
+
daemonSupported: boolean
|
|
53
|
+
daemonInstalled: boolean
|
|
54
|
+
daemonRunning: boolean
|
|
55
|
+
runtimeInstalled: boolean
|
|
56
|
+
privacyConfigured: boolean
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface SetupResult {
|
|
60
|
+
runtimeVersion: string
|
|
61
|
+
serviceInstalled: boolean
|
|
62
|
+
repositoryPrepared: boolean
|
|
63
|
+
compatibilityShared: boolean
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
type SetupStage =
|
|
67
|
+
| 'decisions'
|
|
68
|
+
| 'runtime'
|
|
69
|
+
| 'repository'
|
|
70
|
+
| 'service'
|
|
71
|
+
| 'privacy'
|
|
72
|
+
| 'compatibility'
|
|
73
|
+
|
|
74
|
+
export async function runSetup(args: string[]): Promise<SetupResult | undefined> {
|
|
75
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
76
|
+
printHelp()
|
|
77
|
+
return
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const options = parseSetupOptions(args)
|
|
81
|
+
let stage: SetupStage = 'decisions'
|
|
82
|
+
try {
|
|
83
|
+
const packageRoot = findPackageRoot(options.appDir)
|
|
84
|
+
const serviceStatus = getDaemonServiceStatus()
|
|
85
|
+
const privacy = readPrivacyPreferences()
|
|
86
|
+
const service = await decideService(options, serviceStatus)
|
|
87
|
+
const repository = await decideRepository(options, packageRoot)
|
|
88
|
+
const productAnalytics = await decidePrivacy(
|
|
89
|
+
options,
|
|
90
|
+
'productAnalytics',
|
|
91
|
+
privacy.productAnalytics,
|
|
92
|
+
privacy.configured,
|
|
93
|
+
)
|
|
94
|
+
const crashReports = await decidePrivacy(
|
|
95
|
+
options,
|
|
96
|
+
'crashReports',
|
|
97
|
+
privacy.crashReports,
|
|
98
|
+
privacy.configured,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
const manifest = await sootsimRuntime.fetchManifest()
|
|
102
|
+
const resolvedRuntime = sootsimRuntime.resolveVersion(manifest, { channel: 'stable' })
|
|
103
|
+
const runtimeVersion = resolvedRuntime.version
|
|
104
|
+
const cliVersion = getCliVersion()
|
|
105
|
+
if (cliVersion === '0.0.0') {
|
|
106
|
+
throw new Error('could not resolve the installed rnxsim CLI version')
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
let repositoryPlan: RepositorySetupPlan | null = null
|
|
110
|
+
if (repository && packageRoot) {
|
|
111
|
+
repositoryPlan = planRepositorySetup({
|
|
112
|
+
appDir: packageRoot,
|
|
113
|
+
cliVersion,
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
printIntro(options)
|
|
118
|
+
printMachineSection(options, serviceStatus, service, runtimeVersion)
|
|
119
|
+
printRepositorySection(options, packageRoot, repositoryPlan)
|
|
120
|
+
printPrivacySection(options, productAnalytics, crashReports)
|
|
121
|
+
|
|
122
|
+
stage = 'runtime'
|
|
123
|
+
let installed = false
|
|
124
|
+
if (!options.dryRun) {
|
|
125
|
+
const activeRuntime = readActiveRuntime()
|
|
126
|
+
const result = await sootsimRuntime.install({
|
|
127
|
+
version: runtimeVersion,
|
|
128
|
+
channel: 'stable',
|
|
129
|
+
setActive: true,
|
|
130
|
+
protectVersions: activeRuntime ? [activeRuntime] : [],
|
|
131
|
+
})
|
|
132
|
+
installed = result.installed
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
stage = 'repository'
|
|
136
|
+
if (repositoryPlan) {
|
|
137
|
+
await applyRepositorySetup(repositoryPlan, {
|
|
138
|
+
dryRun: options.dryRun,
|
|
139
|
+
json: options.json,
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
stage = 'service'
|
|
144
|
+
let serviceInstalled = serviceStatus.installed
|
|
145
|
+
if (service && !serviceStatus.installed && !options.dryRun) {
|
|
146
|
+
await daemonInstall({ port: DEFAULT_SOOTSIM_BRIDGE_PORT, force: false })
|
|
147
|
+
serviceInstalled = true
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
stage = 'privacy'
|
|
151
|
+
if (!options.dryRun) {
|
|
152
|
+
writePrivacyPreferences({ productAnalytics, crashReports })
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
stage = 'compatibility'
|
|
156
|
+
const scan = packageRoot ? scanPackage(packageRoot) : null
|
|
157
|
+
const shareCompatibility = await decideCompatibilitySharing(options, scan)
|
|
158
|
+
if (shareCompatibility && scan && packageRoot && !options.dryRun) {
|
|
159
|
+
await shareCompatibilityScan(packageRoot, scan)
|
|
160
|
+
}
|
|
161
|
+
printCompatibilitySection(options, scan, shareCompatibility)
|
|
162
|
+
|
|
163
|
+
const result: SetupResult = {
|
|
164
|
+
runtimeVersion,
|
|
165
|
+
serviceInstalled,
|
|
166
|
+
repositoryPrepared: repositoryPlan !== null,
|
|
167
|
+
compatibilityShared: shareCompatibility && !options.dryRun,
|
|
168
|
+
}
|
|
169
|
+
const cache = runtimeCacheMetadata(runtimeVersion)
|
|
170
|
+
if (options.json) {
|
|
171
|
+
console.log(
|
|
172
|
+
JSON.stringify(
|
|
173
|
+
{
|
|
174
|
+
...result,
|
|
175
|
+
runtimeInstalled: options.dryRun ? false : installed,
|
|
176
|
+
dryRun: options.dryRun,
|
|
177
|
+
cache,
|
|
178
|
+
repositoryOperations: repositoryPlan
|
|
179
|
+
? formatRepositoryOperations(repositoryPlan)
|
|
180
|
+
: [],
|
|
181
|
+
},
|
|
182
|
+
null,
|
|
183
|
+
2,
|
|
184
|
+
),
|
|
185
|
+
)
|
|
186
|
+
} else {
|
|
187
|
+
printReadySection(repositoryPlan)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const counts = scan ? countScanResults(scan) : null
|
|
191
|
+
trackCliEvent({
|
|
192
|
+
event: 'cli_setup_completed',
|
|
193
|
+
properties: {
|
|
194
|
+
service_installed: serviceInstalled,
|
|
195
|
+
repository_prepared: repositoryPlan !== null,
|
|
196
|
+
product_analytics: productAnalytics,
|
|
197
|
+
crash_reports: crashReports,
|
|
198
|
+
compat_supported: counts?.supported ?? 0,
|
|
199
|
+
compat_partial: counts?.partial ?? 0,
|
|
200
|
+
compat_unsupported: counts?.unsupported ?? 0,
|
|
201
|
+
compat_not_yet_verified: counts?.notYetVerified ?? 0,
|
|
202
|
+
from_welcome: options.fromWelcome,
|
|
203
|
+
ci: options.ci,
|
|
204
|
+
dry_run: options.dryRun,
|
|
205
|
+
},
|
|
206
|
+
})
|
|
207
|
+
return result
|
|
208
|
+
} catch (error) {
|
|
209
|
+
const message = boundedMessage(error)
|
|
210
|
+
trackCliEvent({
|
|
211
|
+
event: 'cli_setup_failed',
|
|
212
|
+
properties: { stage, message },
|
|
213
|
+
})
|
|
214
|
+
throw error
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export function readMachineSetupStatus(): MachineSetupStatus {
|
|
219
|
+
const service = getDaemonServiceStatus()
|
|
220
|
+
const lock = readDaemonLockfile()
|
|
221
|
+
const activeRuntime = readActiveRuntime()
|
|
222
|
+
return {
|
|
223
|
+
daemonSupported: service.supported,
|
|
224
|
+
daemonInstalled: service.installed,
|
|
225
|
+
daemonRunning: Boolean(lock && isDaemonLockfileFresh(lock)),
|
|
226
|
+
runtimeInstalled: Boolean(activeRuntime && fs.existsSync(runtimeDir(activeRuntime))),
|
|
227
|
+
privacyConfigured: readPrivacyPreferences().configured,
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export function shouldRunSetupForBareCommand(
|
|
232
|
+
status: MachineSetupStatus = readMachineSetupStatus(),
|
|
233
|
+
): boolean {
|
|
234
|
+
return !status.runtimeInstalled || !status.privacyConfigured
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function parseSetupOptions(args: string[]): SetupOptions {
|
|
238
|
+
const appIndex = args.indexOf('--app')
|
|
239
|
+
const appArg = appIndex >= 0 ? args[appIndex + 1] : undefined
|
|
240
|
+
if (appIndex >= 0 && (!appArg || appArg.startsWith('-'))) {
|
|
241
|
+
throw new Error('--app requires a directory')
|
|
242
|
+
}
|
|
243
|
+
const service = readBooleanFlag(args, '--service', '--no-service')
|
|
244
|
+
const repository = readBooleanFlag(args, '--repo', '--no-repo')
|
|
245
|
+
return {
|
|
246
|
+
appDir: path.resolve(appArg ?? process.cwd()),
|
|
247
|
+
ci: args.includes('--ci'),
|
|
248
|
+
dryRun: args.includes('--dry-run'),
|
|
249
|
+
fromWelcome: args.includes('--from-welcome'),
|
|
250
|
+
json: args.includes('--json'),
|
|
251
|
+
yes: args.includes('--yes') || args.includes('-y'),
|
|
252
|
+
service,
|
|
253
|
+
repository,
|
|
254
|
+
productAnalytics: readOnOffFlag(args, '--analytics'),
|
|
255
|
+
crashReports: readOnOffFlag(args, '--crash-reports'),
|
|
256
|
+
shareCompatibility: args.includes('--share-compat'),
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function readBooleanFlag(
|
|
261
|
+
args: string[],
|
|
262
|
+
positive: string,
|
|
263
|
+
negative: string,
|
|
264
|
+
): boolean | undefined {
|
|
265
|
+
if (args.includes(positive) && args.includes(negative)) {
|
|
266
|
+
throw new Error(`${positive} and ${negative} cannot be used together`)
|
|
267
|
+
}
|
|
268
|
+
if (args.includes(positive)) return true
|
|
269
|
+
if (args.includes(negative)) return false
|
|
270
|
+
return undefined
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function readOnOffFlag(args: string[], name: string): boolean | undefined {
|
|
274
|
+
const equals = args.find((arg) => arg.startsWith(`${name}=`))
|
|
275
|
+
const index = args.indexOf(name)
|
|
276
|
+
const raw = equals?.slice(name.length + 1) ?? (index >= 0 ? args[index + 1] : undefined)
|
|
277
|
+
if (raw === undefined) return undefined
|
|
278
|
+
if (raw === 'on' || raw === 'yes' || raw === 'true') return true
|
|
279
|
+
if (raw === 'off' || raw === 'no' || raw === 'false') return false
|
|
280
|
+
throw new Error(`${name} must be on or off`)
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
async function decideService(
|
|
284
|
+
options: SetupOptions,
|
|
285
|
+
status: ReturnType<typeof getDaemonServiceStatus>,
|
|
286
|
+
): Promise<boolean> {
|
|
287
|
+
if (options.ci) {
|
|
288
|
+
if (options.service === true) throw new Error('--ci cannot install a machine service')
|
|
289
|
+
return false
|
|
290
|
+
}
|
|
291
|
+
if (!status.supported) return false
|
|
292
|
+
if (status.installed && options.service === undefined) return true
|
|
293
|
+
if (options.service !== undefined) return options.service
|
|
294
|
+
if (options.yes) return true
|
|
295
|
+
requireInteractive(options, '--service or --no-service')
|
|
296
|
+
return confirm('Install the background service and shared managed runtime?', true)
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
async function decideRepository(
|
|
300
|
+
options: SetupOptions,
|
|
301
|
+
packageRoot: string | null,
|
|
302
|
+
): Promise<boolean> {
|
|
303
|
+
if (!packageRoot) {
|
|
304
|
+
if (options.repository === true) throw new Error('--repo requires a package.json')
|
|
305
|
+
return false
|
|
306
|
+
}
|
|
307
|
+
if (options.repository !== undefined) return options.repository
|
|
308
|
+
if (options.yes) return true
|
|
309
|
+
requireInteractive(options, '--repo or --no-repo')
|
|
310
|
+
return confirm(`Prepare ${packageRoot} for reproducible rnx runs?`, true)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
async function decidePrivacy(
|
|
314
|
+
options: SetupOptions,
|
|
315
|
+
key: 'productAnalytics' | 'crashReports',
|
|
316
|
+
current: boolean,
|
|
317
|
+
configured: boolean,
|
|
318
|
+
): Promise<boolean> {
|
|
319
|
+
const explicit =
|
|
320
|
+
key === 'productAnalytics' ? options.productAnalytics : options.crashReports
|
|
321
|
+
if (explicit !== undefined) return explicit
|
|
322
|
+
if (configured) return current
|
|
323
|
+
if (options.yes) return true
|
|
324
|
+
const flag =
|
|
325
|
+
key === 'productAnalytics' ? '--analytics on|off' : '--crash-reports on|off'
|
|
326
|
+
requireInteractive(options, flag)
|
|
327
|
+
const question =
|
|
328
|
+
key === 'productAnalytics'
|
|
329
|
+
? 'Share bounded product analytics?'
|
|
330
|
+
: 'Send bounded crash reports?'
|
|
331
|
+
return confirm(question, true)
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
async function decideCompatibilitySharing(
|
|
335
|
+
options: SetupOptions,
|
|
336
|
+
scan: ScanResult | null,
|
|
337
|
+
): Promise<boolean> {
|
|
338
|
+
if (!scan) return false
|
|
339
|
+
if (options.shareCompatibility) return true
|
|
340
|
+
if (options.yes || !process.stdin.isTTY) return false
|
|
341
|
+
return confirm(
|
|
342
|
+
'Share dependency names, requested versions, framework, and this compatibility result?',
|
|
343
|
+
false,
|
|
344
|
+
)
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function requireInteractive(options: SetupOptions, flags: string): void {
|
|
348
|
+
if (process.stdin.isTTY && !options.ci) return
|
|
349
|
+
throw new Error(`non-interactive setup requires ${flags}, or --yes to accept defaults`)
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function scanPackage(packageRoot: string): ScanResult {
|
|
353
|
+
const parsed: unknown = JSON.parse(
|
|
354
|
+
fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8'),
|
|
355
|
+
)
|
|
356
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
357
|
+
throw new Error('package.json must contain an object')
|
|
358
|
+
}
|
|
359
|
+
return scanDeps(parsed)
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
async function shareCompatibilityScan(
|
|
363
|
+
packageRoot: string,
|
|
364
|
+
scan: ScanResult,
|
|
365
|
+
): Promise<void> {
|
|
366
|
+
const parsed: unknown = JSON.parse(
|
|
367
|
+
fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8'),
|
|
368
|
+
)
|
|
369
|
+
if (!parsed || typeof parsed !== 'object')
|
|
370
|
+
throw new Error('package.json must be an object')
|
|
371
|
+
const response = await fetch('https://contrast.dev/api/scan', {
|
|
372
|
+
method: 'POST',
|
|
373
|
+
headers: { 'content-type': 'application/json' },
|
|
374
|
+
body: JSON.stringify(buildCompatibilitySharePayload(parsed, scan)),
|
|
375
|
+
signal: AbortSignal.timeout(10_000),
|
|
376
|
+
})
|
|
377
|
+
if (!response.ok) {
|
|
378
|
+
throw new Error(`compatibility sharing failed with HTTP ${response.status}`)
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
export function buildCompatibilitySharePayload(manifest: object, scan: ScanResult) {
|
|
383
|
+
return {
|
|
384
|
+
dependencies: boundedDependencies(Reflect.get(manifest, 'dependencies')),
|
|
385
|
+
devDependencies: boundedDependencies(Reflect.get(manifest, 'devDependencies')),
|
|
386
|
+
framework: scan.framework,
|
|
387
|
+
result: {
|
|
388
|
+
framework: scan.framework,
|
|
389
|
+
rnVersion: scan.rnVersion,
|
|
390
|
+
packages: scan.packages.slice(0, 200),
|
|
391
|
+
},
|
|
392
|
+
source: 'desktop',
|
|
393
|
+
shared: true,
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
function boundedDependencies(value: unknown): Record<string, string> {
|
|
398
|
+
if (!value || typeof value !== 'object') return {}
|
|
399
|
+
const output: Record<string, string> = {}
|
|
400
|
+
for (const [name, version] of Object.entries(value).slice(0, 200)) {
|
|
401
|
+
if (typeof version !== 'string') continue
|
|
402
|
+
output[name.slice(0, 160)] = version.slice(0, 80)
|
|
403
|
+
}
|
|
404
|
+
return output
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function runtimeCacheMetadata(runtimeVersion: string) {
|
|
408
|
+
const platform = os.platform()
|
|
409
|
+
const arch = os.arch()
|
|
410
|
+
return {
|
|
411
|
+
path: runtimeDir(runtimeVersion),
|
|
412
|
+
key: `sootsim-runtime-${platform}-${arch}-${runtimeVersion}`,
|
|
413
|
+
inputs: { platform, arch, runtimeVersion },
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function printIntro(options: SetupOptions): void {
|
|
418
|
+
if (options.json) return
|
|
419
|
+
console.log(`\n ${options.fromWelcome ? 'welcome to rnx' : 'rnxsim setup'}`)
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
function printMachineSection(
|
|
423
|
+
options: SetupOptions,
|
|
424
|
+
status: ReturnType<typeof getDaemonServiceStatus>,
|
|
425
|
+
service: boolean,
|
|
426
|
+
runtimeVersion: string,
|
|
427
|
+
): void {
|
|
428
|
+
if (options.json) return
|
|
429
|
+
console.log(`\n 1. machine`)
|
|
430
|
+
console.log(` stable runtime: ${runtimeVersion}`)
|
|
431
|
+
console.log(
|
|
432
|
+
` background service: ${status.supported ? (service ? 'install' : 'skip') : 'unsupported on this platform'}`,
|
|
433
|
+
)
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
function printRepositorySection(
|
|
437
|
+
options: SetupOptions,
|
|
438
|
+
packageRoot: string | null,
|
|
439
|
+
plan: RepositorySetupPlan | null,
|
|
440
|
+
): void {
|
|
441
|
+
if (options.json) return
|
|
442
|
+
console.log(`\n 2. repository`)
|
|
443
|
+
if (!packageRoot) {
|
|
444
|
+
console.log(` no package.json found; repository preparation skipped`)
|
|
445
|
+
return
|
|
446
|
+
}
|
|
447
|
+
if (!plan) {
|
|
448
|
+
console.log(` skipped for ${packageRoot}`)
|
|
449
|
+
return
|
|
450
|
+
}
|
|
451
|
+
console.log(` package manager: ${detectPreferredPackageManager(packageRoot)}`)
|
|
452
|
+
for (const operation of formatRepositoryOperations(plan)) {
|
|
453
|
+
console.log(` ${options.dryRun ? 'would run' : 'run'}: ${operation}`)
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
function printPrivacySection(
|
|
458
|
+
options: SetupOptions,
|
|
459
|
+
productAnalytics: boolean,
|
|
460
|
+
crashReports: boolean,
|
|
461
|
+
): void {
|
|
462
|
+
if (options.json) return
|
|
463
|
+
console.log(`\n 3. privacy`)
|
|
464
|
+
console.log(` product analytics: ${productAnalytics ? 'on' : 'off'}`)
|
|
465
|
+
console.log(
|
|
466
|
+
` command, feature, version, platform, and bounded performance events`,
|
|
467
|
+
)
|
|
468
|
+
console.log(` crash reports: ${crashReports ? 'on' : 'off'}`)
|
|
469
|
+
console.log(
|
|
470
|
+
` error type, message, stack, runtime version, platform, and bounded dependency summary`,
|
|
471
|
+
)
|
|
472
|
+
console.log(
|
|
473
|
+
` source files, environment values, terminal output, app data, screenshots, and recordings are not included`,
|
|
474
|
+
)
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
function printCompatibilitySection(
|
|
478
|
+
options: SetupOptions,
|
|
479
|
+
scan: ScanResult | null,
|
|
480
|
+
shared: boolean,
|
|
481
|
+
): void {
|
|
482
|
+
if (options.json) return
|
|
483
|
+
console.log(`\n 4. compatibility`)
|
|
484
|
+
if (!scan) {
|
|
485
|
+
console.log(` no package.json found; run \`rnxsim compat\` inside an app later`)
|
|
486
|
+
return
|
|
487
|
+
}
|
|
488
|
+
console.log(` ${formatScanCounts(scan)}`)
|
|
489
|
+
for (const line of formatDetailedScanLines(scan)) console.log(` ${line}`)
|
|
490
|
+
console.log(` ${COMPAT_RESULT_CAVEAT}`)
|
|
491
|
+
console.log(` dependency sharing: ${shared ? 'yes' : 'no'}`)
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
function printReadySection(repository: RepositorySetupPlan | null): void {
|
|
495
|
+
console.log(`\n 5. ready`)
|
|
496
|
+
if (repository) {
|
|
497
|
+
const command =
|
|
498
|
+
repository.packageManager === 'bun'
|
|
499
|
+
? 'bun run sootsim'
|
|
500
|
+
: `${repository.packageManager} run rnxsim`
|
|
501
|
+
console.log(` start your app normally, then ${command} -- <port>`)
|
|
502
|
+
} else {
|
|
503
|
+
console.log(` start your app normally, then rnxsim open <port>`)
|
|
504
|
+
}
|
|
505
|
+
console.log(
|
|
506
|
+
` useful next commands: rnxsim describe; rnxsim get errors; rnxsim compat`,
|
|
507
|
+
)
|
|
508
|
+
console.log(
|
|
509
|
+
` install agent skills with \`rnxsim skill install\`, then start a new session`,
|
|
510
|
+
)
|
|
511
|
+
console.log(
|
|
512
|
+
` if a concrete rnx seam is missing or broken, preview \`rnxsim report-issue\` and confirm separately`,
|
|
513
|
+
)
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
function boundedMessage(error: unknown): string {
|
|
517
|
+
const message = error instanceof Error ? error.message : String(error)
|
|
518
|
+
return message.replace(/(?:\/?[\w.-]+)+/g, '<path>').slice(0, 240)
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
function printHelp(): void {
|
|
522
|
+
console.log(`
|
|
523
|
+
rnxsim setup — configure a machine and optionally prepare the current repository
|
|
524
|
+
|
|
525
|
+
usage:
|
|
526
|
+
rnxsim setup
|
|
527
|
+
rnxsim setup --yes
|
|
528
|
+
rnxsim setup --ci --yes --json
|
|
529
|
+
rnxsim setup --dry-run --yes
|
|
530
|
+
|
|
531
|
+
decisions:
|
|
532
|
+
--service | --no-service
|
|
533
|
+
--repo | --no-repo
|
|
534
|
+
--analytics on|off
|
|
535
|
+
--crash-reports on|off
|
|
536
|
+
--share-compat
|
|
537
|
+
|
|
538
|
+
automation:
|
|
539
|
+
--yes accept defaults; compatibility sharing still defaults off
|
|
540
|
+
--ci never prompt or install a background service
|
|
541
|
+
--json emit runtime/cache metadata as JSON
|
|
542
|
+
--dry-run print exact repository operations without changing the machine
|
|
543
|
+
--app DIR use DIR as the repository search start
|
|
544
|
+
`)
|
|
545
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { callInBridge, createBridgeFromParsed, parseBridgeCliArgs } from '../ws-bridge'
|
|
2
|
+
|
|
3
|
+
export type ShellBooleanModeAction = 'on' | 'off' | 'toggle'
|
|
4
|
+
|
|
5
|
+
export interface ShellBooleanModeOptions {
|
|
6
|
+
port?: number
|
|
7
|
+
verbose?: boolean
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface ShellBooleanModeConfig {
|
|
11
|
+
modeKey: string
|
|
12
|
+
displayName: string
|
|
13
|
+
actionId: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ShellBooleanModeResult {
|
|
17
|
+
current: boolean
|
|
18
|
+
target: boolean
|
|
19
|
+
changed: boolean
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function parseShellBooleanModeAction(args: string[]): ShellBooleanModeAction {
|
|
23
|
+
const action = args[0]?.toLowerCase() ?? 'toggle'
|
|
24
|
+
if (action !== 'on' && action !== 'off' && action !== 'toggle') {
|
|
25
|
+
console.error(` unknown argument: "${action}" (expected on | off | toggle)`)
|
|
26
|
+
process.exit(1)
|
|
27
|
+
}
|
|
28
|
+
return action
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export async function runShellBooleanMode(
|
|
32
|
+
args: string[],
|
|
33
|
+
opts: ShellBooleanModeOptions,
|
|
34
|
+
config: ShellBooleanModeConfig,
|
|
35
|
+
): Promise<ShellBooleanModeResult> {
|
|
36
|
+
const parsed = parseBridgeCliArgs(args, { port: opts.port })
|
|
37
|
+
const action = parseShellBooleanModeAction(parsed.positional)
|
|
38
|
+
const bridge = createBridgeFromParsed({ ...parsed, commandTimeoutMs: 5000 })
|
|
39
|
+
try {
|
|
40
|
+
const settings = await callInBridge<Record<string, unknown>>(
|
|
41
|
+
bridge,
|
|
42
|
+
'SootSim.bridges.settings.get',
|
|
43
|
+
)
|
|
44
|
+
const current = Boolean(settings?.[config.modeKey])
|
|
45
|
+
const target = action === 'on' ? true : action === 'off' ? false : !current
|
|
46
|
+
if (current === target) {
|
|
47
|
+
console.log(` ${config.displayName}: already ${target ? 'on' : 'off'}`)
|
|
48
|
+
return { current, target, changed: false }
|
|
49
|
+
}
|
|
50
|
+
const changed = await bridge.send({
|
|
51
|
+
type: 'evaluate',
|
|
52
|
+
acquireLock: true,
|
|
53
|
+
code: `(async () => {
|
|
54
|
+
const modeKey = ${JSON.stringify(config.modeKey)}
|
|
55
|
+
const target = ${JSON.stringify(target)}
|
|
56
|
+
window.dispatchEvent(new CustomEvent('sootsim:shell-command', {
|
|
57
|
+
detail: { type: 'fire-action', id: ${JSON.stringify(config.actionId)} },
|
|
58
|
+
}))
|
|
59
|
+
const deadline = Date.now() + 1200
|
|
60
|
+
while (Date.now() < deadline) {
|
|
61
|
+
if (Boolean(window.SootSim?.bridges?.settings?.get?.()?.[modeKey]) === target) {
|
|
62
|
+
return true
|
|
63
|
+
}
|
|
64
|
+
await new Promise((resolve) => setTimeout(resolve, 40))
|
|
65
|
+
}
|
|
66
|
+
return false
|
|
67
|
+
})()`,
|
|
68
|
+
})
|
|
69
|
+
if (!changed) {
|
|
70
|
+
throw new Error(
|
|
71
|
+
`${config.displayName} did not change to ${target ? 'on' : 'off'}; the live shell may not support this mode`,
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
console.log(
|
|
75
|
+
` ${config.displayName}: ${current ? 'on' : 'off'} -> ${target ? 'on' : 'off'}`,
|
|
76
|
+
)
|
|
77
|
+
return { current, target, changed: true }
|
|
78
|
+
} finally {
|
|
79
|
+
bridge.close()
|
|
80
|
+
}
|
|
81
|
+
}
|