rnxsim 0.1.376 → 0.1.378
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 +28 -25
- package/cli/app-config.ts +9 -12
- package/cli/app-fonts.ts +3 -3
- package/cli/app-project.ts +8 -8
- package/cli/auth.ts +7 -9
- package/cli/bin.ts +16 -31
- package/cli/bridge-flow-runner.ts +3 -3
- package/cli/browser-backend.ts +44 -0
- package/cli/command-contract.ts +221 -0
- package/cli/command-registry.ts +291 -0
- package/cli/commands/agent-wrapper.ts +2 -2
- package/cli/commands/app-fonts.ts +2 -2
- package/cli/commands/assert.ts +3 -3
- package/cli/commands/auth.ts +1 -1
- package/cli/commands/box/cloud-box.ts +1 -1
- package/cli/commands/box/plane-share.ts +2 -2
- package/cli/commands/box.ts +4 -6
- package/cli/commands/compat.ts +1 -1
- package/cli/commands/config.ts +2 -2
- package/cli/commands/control.ts +29 -29
- package/cli/commands/cpu-profile.ts +7 -7
- package/cli/commands/daemon-mac-app.ts +7 -7
- package/cli/commands/daemon.ts +10 -10
- package/cli/commands/debug.ts +11 -11
- package/cli/commands/detox.ts +13 -13
- package/cli/commands/diagnose.ts +6 -6
- package/cli/commands/do-chain.ts +1 -2
- package/cli/commands/electron.ts +1 -3
- package/cli/commands/film.ts +3 -3
- package/cli/commands/flow.ts +43 -43
- package/cli/commands/inspect/count.ts +1 -1
- package/cli/commands/inspect/describe.ts +1 -1
- package/cli/commands/inspect/env.ts +2 -2
- package/cli/commands/inspect/get-layout.ts +1 -1
- package/cli/commands/inspect/keyboard.ts +1 -1
- package/cli/commands/inspect/list.ts +1 -1
- package/cli/commands/inspect/memory.ts +1 -1
- package/cli/commands/inspect/resolve-target.ts +1 -1
- package/cli/commands/inspect/screens.ts +1 -1
- package/cli/commands/inspect/tree.ts +1 -1
- package/cli/commands/inspect/url.ts +1 -1
- package/cli/commands/inspect/wait-event.ts +5 -5
- package/cli/commands/inspect.ts +34 -34
- package/cli/commands/install-desktop.ts +3 -3
- package/cli/commands/login.ts +6 -6
- package/cli/commands/maestro-generate.ts +5 -5
- package/cli/commands/maestro.ts +5 -5
- package/cli/commands/profile.ts +1 -1
- package/cli/commands/record.ts +9 -9
- package/cli/commands/runtime.ts +18 -18
- package/cli/commands/screenshot-command.ts +1 -1
- package/cli/commands/screenshot-layers.ts +5 -5
- package/cli/commands/screenshot-mode.ts +1 -1
- package/cli/commands/screenshot.ts +8 -8
- package/cli/commands/screenshots-capture.ts +5 -5
- package/cli/commands/serve.ts +3 -3
- package/cli/commands/setup.ts +20 -12
- package/cli/commands/skills.ts +5 -5
- package/cli/commands/slides.ts +1 -1
- package/cli/commands/telemetry.ts +1 -1
- package/cli/commands/three-mode.ts +1 -1
- package/cli/commands/timeline.ts +8 -8
- package/cli/commands/upgrade.ts +116 -131
- package/cli/commands/upload.ts +12 -12
- package/cli/commands/version.ts +7 -7
- package/cli/commands/what-happened.ts +9 -9
- package/cli/current-sim.ts +3 -3
- package/cli/desktop-companion.ts +1 -1
- package/cli/drivers/playwright.ts +9 -9
- package/cli/drivers/registry.ts +1 -1
- package/cli/drivers/types.ts +1 -1
- package/cli/flow-file.ts +2 -2
- package/cli/flow-session.ts +1 -1
- package/cli/help-core.ts +136 -0
- package/cli/help.ts +17 -53
- package/cli/hints.ts +5 -5
- package/cli/inspect-notice-state.ts +1 -1
- package/cli/maestro-js.ts +1 -1
- package/cli/outbound-endpoints.ts +23 -5
- package/cli/parse-args.ts +19 -66
- package/cli/recording-access.ts +1 -1
- package/cli/registry.ts +1 -0
- package/cli/run-registry.ts +1 -1
- package/cli/run-rnx-core.ts +148 -0
- package/cli/run-rnx.ts +6 -9
- package/cli/runtime-notes.ts +3 -3
- package/cli/standalone.ts +4 -0
- package/cli/ws-bridge.ts +8 -8
- package/detox/config-loader.ts +2 -2
- package/detox/index.ts +8 -8
- package/detox/jest-preset.cjs +1 -1
- package/detox/navigation.ts +2 -2
- package/dist-lib/agent-daemon-client.cjs +5 -5
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +2 -2
- package/dist-lib/agent-sessions.cjs +10 -10
- package/dist-lib/attached-projects.cjs +6 -6
- package/dist-lib/auth/shared-session.cjs +6 -6
- 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-input.cjs +1 -1
- package/dist-lib/bridge-contract-input.mjs +1 -1
- package/dist-lib/bridge-contract.cjs +1 -1
- package/dist-lib/bridge-contract.mjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/config.cjs +25 -25
- package/dist-lib/detox/index.cjs +73 -31
- package/dist-lib/detox/jest-preset.cjs +1 -1
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +29 -29
- package/dist-lib/host/bridge-host.cjs +128 -49
- 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/replacement-module-handler.cjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +14 -14
- 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-production-bundle.cjs +1 -1
- package/dist-lib/metro-production-bundle.mjs +1 -1
- package/dist-lib/metro.cjs +8 -8
- package/dist-lib/profiles.cjs +12 -12
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/react-native-host-modules.cjs +1 -1
- package/dist-lib/react-native-host-modules.mjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +8 -8
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +329 -160
- package/dist-lib/vite.cjs +9 -9
- package/package.json +4 -11
- package/scripts/dev-server-scanner.ts +2 -2
- package/scripts/optional-demo-registry.ts +1 -1
- package/skills/contrast/SKILL.md +3 -3
- package/skills/rnx-debug/SKILL.md +1 -1
- package/skills/rnx-test/SKILL.md +2 -2
- package/src/agent-identity.ts +1 -1
- package/src/agent-sessions.ts +7 -5
- package/src/cli-version.ts +12 -4
- package/src/config.ts +26 -28
- package/src/disk-cleanup.ts +11 -11
- package/src/home-paths.ts +28 -28
- package/src/host/bridge-host.ts +16 -16
- package/src/metro-plugin.ts +2 -2
- package/src/profiles.ts +2 -2
- package/src/runtime-assets.ts +7 -7
- package/src/runtime-delivery.ts +13 -13
- package/src/screenshots/orchestrate.ts +1 -1
- package/src/screenshots/schema.ts +2 -2
- package/src/skills/builtin/a11y-review.ts +2 -2
- package/src/skills/builtin/compat-check.ts +2 -2
- package/src/skills/builtin/maestro-test.ts +2 -2
- package/src/skills/builtin/perf-profile.ts +2 -2
- package/src/skills/builtin/screenshot-all.ts +2 -2
- package/src/skills/builtin/visual-diff.ts +2 -2
- package/src/skills/registry.ts +8 -8
- package/src/skills/types.ts +1 -1
- package/src/vite-plugin-one.ts +3 -3
- package/src/vite-plugin.ts +15 -2
- package/dist-cli/bin.js +0 -15
- package/dist-cli/chunks/agent-H42FCKFF.js +0 -48
- package/dist-cli/chunks/agent-wrapper-BBZKTZS6.js +0 -17
- package/dist-cli/chunks/app-fonts-43VXIKF4.js +0 -4
- package/dist-cli/chunks/assert-IXOLVO5Z.js +0 -49
- package/dist-cli/chunks/auth-KFMFB6FU.js +0 -12
- package/dist-cli/chunks/beta-5AO3SJB7.js +0 -4
- package/dist-cli/chunks/box-ZHM66L6K.js +0 -1730
- package/dist-cli/chunks/camera-FNJVFCDQ.js +0 -33
- package/dist-cli/chunks/chunk-37MCSPTE.js +0 -71
- package/dist-cli/chunks/chunk-3PEMSUAQ.js +0 -30
- package/dist-cli/chunks/chunk-4TQ5HOK3.js +0 -7
- package/dist-cli/chunks/chunk-5YZYDEMI.js +0 -4
- package/dist-cli/chunks/chunk-6CV3R3XD.js +0 -15
- package/dist-cli/chunks/chunk-7LGK5XU6.js +0 -4
- package/dist-cli/chunks/chunk-7R2TK2NY.js +0 -4
- package/dist-cli/chunks/chunk-7VZZQQEE.js +0 -497
- package/dist-cli/chunks/chunk-AFOVILIL.js +0 -130
- package/dist-cli/chunks/chunk-BEU7CD7E.js +0 -9
- package/dist-cli/chunks/chunk-CE4JQJ6Y.js +0 -6
- package/dist-cli/chunks/chunk-CIE6CZXL.js +0 -142
- package/dist-cli/chunks/chunk-CSJ7L7ZL.js +0 -312
- package/dist-cli/chunks/chunk-CWCQP53A.js +0 -27
- package/dist-cli/chunks/chunk-DCS5FK5N.js +0 -7
- package/dist-cli/chunks/chunk-DEV3E3MV.js +0 -4
- package/dist-cli/chunks/chunk-DGJMIVZM.js +0 -5
- package/dist-cli/chunks/chunk-DGX3MN65.js +0 -5
- package/dist-cli/chunks/chunk-DNPQMTW5.js +0 -4
- package/dist-cli/chunks/chunk-DOVBJBVD.js +0 -5
- package/dist-cli/chunks/chunk-DPBJ3S3J.js +0 -3
- package/dist-cli/chunks/chunk-FVZBGPCU.js +0 -4
- package/dist-cli/chunks/chunk-GDKMOIUT.js +0 -4
- package/dist-cli/chunks/chunk-GIF2NJCS.js +0 -32
- package/dist-cli/chunks/chunk-GZE57ORL.js +0 -4
- package/dist-cli/chunks/chunk-H3U56DKI.js +0 -24
- package/dist-cli/chunks/chunk-HZLOYAPH.js +0 -4
- package/dist-cli/chunks/chunk-J2IKAEU2.js +0 -4
- package/dist-cli/chunks/chunk-JXAXYK7W.js +0 -11
- package/dist-cli/chunks/chunk-KJE2O2GK.js +0 -4
- package/dist-cli/chunks/chunk-KMNVDZZI.js +0 -423
- package/dist-cli/chunks/chunk-LC3QRIRB.js +0 -10
- package/dist-cli/chunks/chunk-LGFTAQYC.js +0 -4
- package/dist-cli/chunks/chunk-LQMUA5IY.js +0 -4
- package/dist-cli/chunks/chunk-MFIQTWC5.js +0 -4
- package/dist-cli/chunks/chunk-MGALNF2F.js +0 -7
- package/dist-cli/chunks/chunk-MLBZZHOY.js +0 -4
- package/dist-cli/chunks/chunk-NNRF7GIB.js +0 -107
- package/dist-cli/chunks/chunk-NORLYTTO.js +0 -7
- package/dist-cli/chunks/chunk-P6KVGV3H.js +0 -14
- package/dist-cli/chunks/chunk-PAJTUK33.js +0 -4
- package/dist-cli/chunks/chunk-QELIC5XP.js +0 -4
- package/dist-cli/chunks/chunk-QRDF33WD.js +0 -11
- package/dist-cli/chunks/chunk-R76BA7C7.js +0 -535
- package/dist-cli/chunks/chunk-RVEB4CZ2.js +0 -4
- package/dist-cli/chunks/chunk-SK4M7NXT.js +0 -5
- package/dist-cli/chunks/chunk-SKMG5DD7.js +0 -5
- package/dist-cli/chunks/chunk-TEESPOYR.js +0 -4
- package/dist-cli/chunks/chunk-TH2UFGVP.js +0 -4
- package/dist-cli/chunks/chunk-TLP3T3VO.js +0 -4
- package/dist-cli/chunks/chunk-TZUABDIJ.js +0 -38
- package/dist-cli/chunks/chunk-UB2W6OQM.js +0 -99
- package/dist-cli/chunks/chunk-UYVXALPB.js +0 -506
- package/dist-cli/chunks/chunk-VQDYFFIG.js +0 -5
- package/dist-cli/chunks/chunk-VWCNJPCJ.js +0 -5
- package/dist-cli/chunks/chunk-VZIK4WIS.js +0 -74
- package/dist-cli/chunks/chunk-W3FNXAQP.js +0 -4
- package/dist-cli/chunks/chunk-XCDNVNP3.js +0 -4
- package/dist-cli/chunks/chunk-XSVILA4Z.js +0 -4
- package/dist-cli/chunks/chunk-XUTJ7ZWD.js +0 -4
- package/dist-cli/chunks/chunk-YTXY3MHW.js +0 -4
- package/dist-cli/chunks/chunk-ZF7PVX44.js +0 -28
- package/dist-cli/chunks/chunk-ZSSG7OR7.js +0 -4
- package/dist-cli/chunks/cleanup-MLOK2OZA.js +0 -25
- package/dist-cli/chunks/cli-version-OBNR366V.js +0 -4
- package/dist-cli/chunks/compat-SHMFSKU7.js +0 -23
- package/dist-cli/chunks/config-TPEAEUJ2.js +0 -13
- package/dist-cli/chunks/connect-3LEXWTE5.js +0 -4
- package/dist-cli/chunks/control-Z3FWA6BO.js +0 -4
- package/dist-cli/chunks/daemon-RSVYSC65.js +0 -4
- package/dist-cli/chunks/debug-GUVAK2KR.js +0 -200
- package/dist-cli/chunks/desktop-OOP2PTKP.js +0 -31
- package/dist-cli/chunks/detox-C2ILVBEC.js +0 -52
- package/dist-cli/chunks/device-NXIQQJWR.js +0 -18
- package/dist-cli/chunks/diagnose-2JBGYE5L.js +0 -43
- package/dist-cli/chunks/disk-cleanup-VURWJYQV.js +0 -4
- package/dist-cli/chunks/do-chain-DJ4UQC7A.js +0 -5
- package/dist-cli/chunks/drivers-JMA2OIKU.js +0 -4
- package/dist-cli/chunks/env-KTNPKEZR.js +0 -4
- package/dist-cli/chunks/film-DCPS7EID.js +0 -74
- package/dist-cli/chunks/flow-4DZ7B2OA.js +0 -4
- package/dist-cli/chunks/help-34CJMQY2.js +0 -4
- package/dist-cli/chunks/hidden-runtime-alias-HHT2C7WE.js +0 -4
- package/dist-cli/chunks/home-paths-KTPGCPMS.js +0 -4
- package/dist-cli/chunks/inspect-JF5WYJRD.js +0 -4
- package/dist-cli/chunks/install-desktop-ZIC4CDXI.js +0 -4
- package/dist-cli/chunks/login-TTJAOI2Q.js +0 -26
- package/dist-cli/chunks/logout-ERAQ6SKW.js +0 -4
- package/dist-cli/chunks/maestro-W46QCF77.js +0 -108
- package/dist-cli/chunks/maestro-generate-VBLM3MTU.js +0 -36
- package/dist-cli/chunks/mode-ZEDZK7R7.js +0 -26
- package/dist-cli/chunks/optional-demo-registry-ZUTPSVYQ.js +0 -4
- package/dist-cli/chunks/perf-YVT2WXT4.js +0 -48
- package/dist-cli/chunks/permissions-L7VVDHFP.js +0 -13
- package/dist-cli/chunks/platform-7TJOU2FB.js +0 -6
- package/dist-cli/chunks/privacy-57UOTB5J.js +0 -4
- package/dist-cli/chunks/record-VXG37P7U.js +0 -72
- package/dist-cli/chunks/report-issue-WNNOBZHC.js +0 -29
- package/dist-cli/chunks/reset-H5NBFE5U.js +0 -4
- package/dist-cli/chunks/resolve-target-57TK5WLE.js +0 -4
- package/dist-cli/chunks/runtime-QU2NIF2K.js +0 -4
- package/dist-cli/chunks/screenshot-command-AN56TTG7.js +0 -159
- package/dist-cli/chunks/screenshot-layers-3W5R7DB2.js +0 -20
- package/dist-cli/chunks/screenshots-capture-6AWJY7XZ.js +0 -42
- package/dist-cli/chunks/serve-GLYO5Q7J.js +0 -56
- package/dist-cli/chunks/setup-UA2HLD7S.js +0 -4
- package/dist-cli/chunks/sim-client-5C2RDQQO.js +0 -4
- package/dist-cli/chunks/skills-EYXWBRNQ.js +0 -50
- package/dist-cli/chunks/state-REJ7W6K3.js +0 -14
- package/dist-cli/chunks/storage-CFMDHI3V.js +0 -37
- package/dist-cli/chunks/store-XMCUA45G.js +0 -4
- package/dist-cli/chunks/telemetry-FBL3NAKB.js +0 -4
- package/dist-cli/chunks/timeline-HMCHN5FO.js +0 -24
- package/dist-cli/chunks/upgrade-2QSPAA3P.js +0 -7
- package/dist-cli/chunks/upload-DUQBKZYV.js +0 -4
- package/dist-cli/chunks/version-IOA6QFGB.js +0 -6
- package/dist-cli/chunks/web-NCGUYVCJ.js +0 -4
- package/dist-cli/chunks/welcome-QYGSQCWQ.js +0 -5
- package/dist-cli/chunks/what-happened-YTOUK4LO.js +0 -25
- package/dist-cli/chunks/ws-bridge-OF4OZARG.js +0 -4
- package/scripts/postinstall.cjs +0 -3
- package/scripts/preuninstall.cjs +0 -118
package/src/host/bridge-host.ts
CHANGED
|
@@ -16,7 +16,7 @@ import { getCliVersion } from '../cli-version.ts'
|
|
|
16
16
|
import {
|
|
17
17
|
activeRuntimeDir as getActiveRuntimeDir,
|
|
18
18
|
claimDaemonLockfile,
|
|
19
|
-
|
|
19
|
+
ensureRnxHome,
|
|
20
20
|
isSootsimDevCheckout,
|
|
21
21
|
readActiveRuntime,
|
|
22
22
|
readSharedConfig,
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
writeRuntimeUpgradeNotice,
|
|
29
29
|
writeSharedConfig,
|
|
30
30
|
cameraFixturesDir,
|
|
31
|
-
|
|
31
|
+
rnxHomeDir,
|
|
32
32
|
type DaemonLockfile,
|
|
33
33
|
type DevBridgeLockfile,
|
|
34
34
|
type SharedConfig,
|
|
@@ -39,7 +39,7 @@ import {
|
|
|
39
39
|
resolveRuntimeRootForHostname,
|
|
40
40
|
runtimeVersionFromHostname,
|
|
41
41
|
} from '../runtime-assets.ts'
|
|
42
|
-
import {
|
|
42
|
+
import { rnxRuntime } from '../runtime-delivery.ts'
|
|
43
43
|
import { AgentHost, type AgentHostOptions } from './agent-host.ts'
|
|
44
44
|
import {
|
|
45
45
|
handleAppApiRequest,
|
|
@@ -226,13 +226,13 @@ export interface BridgeHostOptions {
|
|
|
226
226
|
/** try preferred port, then port+1, port+2, …, up to this many attempts
|
|
227
227
|
* before giving up. defaults to 10. set 1 to disable fallback. */
|
|
228
228
|
portFallbackCount?: number
|
|
229
|
-
/** when true, write ~/.
|
|
229
|
+
/** when true, write ~/.rnx/daemon.json on successful bind + update
|
|
230
230
|
* it on a heartbeat interval + remove it on close. only the standalone
|
|
231
231
|
* `sootsim serve` process should set this — tests, vite plugin, and
|
|
232
232
|
* anything embedded should leave it off to avoid clobbering a real
|
|
233
233
|
* daemon's lockfile. defaults to false. */
|
|
234
234
|
writeLockfile?: boolean
|
|
235
|
-
/** when true, write an owner-scoped record under ~/.
|
|
235
|
+
/** when true, write an owner-scoped record under ~/.rnx/dev-bridges on
|
|
236
236
|
* successful bind, update it on a heartbeat interval, and remove only that
|
|
237
237
|
* record on close. the Vite dev shell sets this so local CLI commands can
|
|
238
238
|
* address every live source bridge without concurrent worktrees replacing
|
|
@@ -303,7 +303,7 @@ const HTTP_MIME_TYPES: Record<string, string> = {
|
|
|
303
303
|
'.mov': 'video/quicktime',
|
|
304
304
|
}
|
|
305
305
|
|
|
306
|
-
// `rnx camera play` stages a video under ~/.
|
|
306
|
+
// `rnx camera play` stages a video under ~/.rnx/camera-fixtures and the
|
|
307
307
|
// simulator plays it as the camera feed. the route below serves that one
|
|
308
308
|
// directory, addressed by basename only.
|
|
309
309
|
const CAMERA_FIXTURE_ROUTE = '/__camera-fixtures/'
|
|
@@ -313,7 +313,7 @@ const CAMERA_FIXTURE_ROUTE = '/__camera-fixtures/'
|
|
|
313
313
|
const CAMERA_FIXTURE_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/
|
|
314
314
|
|
|
315
315
|
/** inject host-provided globals into the served runtime html:
|
|
316
|
-
* - `window.__sootsimSharedConfig` — parsed `~/.
|
|
316
|
+
* - `window.__sootsimSharedConfig` — parsed `~/.rnx/config.json`,
|
|
317
317
|
* read during engine settingsStore module init (see
|
|
318
318
|
* settings/persistence.ts). mirrors the inject-into-html plugin in the
|
|
319
319
|
* shell vite dev server so dev and prod surfaces both produce it.
|
|
@@ -684,7 +684,7 @@ export class SootSimBridgeHost {
|
|
|
684
684
|
// are handled in-daemon; install runs entirely inside the CLI so
|
|
685
685
|
// we don't need a daemon-side handler for it.
|
|
686
686
|
if (msg.type === 'runtime:list') {
|
|
687
|
-
const versions =
|
|
687
|
+
const versions = rnxRuntime.listInstalled()
|
|
688
688
|
const active = this.getActiveRuntime()
|
|
689
689
|
const reply = {
|
|
690
690
|
type: 'runtime:list:ok',
|
|
@@ -700,7 +700,7 @@ export class SootSimBridgeHost {
|
|
|
700
700
|
}
|
|
701
701
|
if (msg.type === 'runtime:use') {
|
|
702
702
|
const version = typeof msg.version === 'string' ? msg.version : ''
|
|
703
|
-
const installed =
|
|
703
|
+
const installed = rnxRuntime.listInstalled()
|
|
704
704
|
if (!installed.includes(version)) {
|
|
705
705
|
try {
|
|
706
706
|
ws.send(
|
|
@@ -809,7 +809,7 @@ export class SootSimBridgeHost {
|
|
|
809
809
|
return
|
|
810
810
|
}
|
|
811
811
|
|
|
812
|
-
// write a partial patch into ~/.
|
|
812
|
+
// write a partial patch into ~/.rnx/config.json. fired by the
|
|
813
813
|
// engine's settingsStore when a persisted key flips in a browser
|
|
814
814
|
// tab (which has no fs access of its own). after the merge, we
|
|
815
815
|
// broadcast the new full snapshot to every connected sim so any
|
|
@@ -1140,7 +1140,7 @@ export class SootSimBridgeHost {
|
|
|
1140
1140
|
|
|
1141
1141
|
if (this.shouldWriteLockfile) {
|
|
1142
1142
|
try {
|
|
1143
|
-
|
|
1143
|
+
ensureRnxHome()
|
|
1144
1144
|
// atomic claim: bail if another fresh daemon's lockfile already
|
|
1145
1145
|
// exists (stale ones are overwritten). last line of defense
|
|
1146
1146
|
// against two daemons clobbering the same file between the
|
|
@@ -1289,7 +1289,7 @@ export class SootSimBridgeHost {
|
|
|
1289
1289
|
}
|
|
1290
1290
|
|
|
1291
1291
|
// serves one staged camera fixture. addressed by basename inside
|
|
1292
|
-
// ~/.
|
|
1292
|
+
// ~/.rnx/camera-fixtures, never by a caller-supplied path, so there is
|
|
1293
1293
|
// no traversal surface to defend: a name that is not a plain basename is
|
|
1294
1294
|
// rejected outright. range support is not optional here — chrome asks for
|
|
1295
1295
|
// byte ranges on media and cannot seek or loop a fixture without it.
|
|
@@ -1409,14 +1409,14 @@ export class SootSimBridgeHost {
|
|
|
1409
1409
|
|
|
1410
1410
|
private startRuntimeUpdater() {
|
|
1411
1411
|
if (!this.shouldWriteLockfile || this.runtimeUpdateTimer) return
|
|
1412
|
-
if (fs.existsSync(path.join(
|
|
1413
|
-
// an isolated dev daemon (explicit
|
|
1412
|
+
if (fs.existsSync(path.join(rnxHomeDir(), 'runtime-update-disabled'))) return
|
|
1413
|
+
// an isolated dev daemon (explicit RNX_HOME, dev checkout, nothing
|
|
1414
1414
|
// staged) serves the repo's public/sootsim build. auto-installing the
|
|
1415
1415
|
// published runtime here would stage it active and shadow that dev build
|
|
1416
1416
|
// (runtime-assets prefers a staged runtime under an explicit home), so the
|
|
1417
1417
|
// daemon would silently validate published code instead of the checkout.
|
|
1418
1418
|
// local-publish writes the marker above when it stages a source build.
|
|
1419
|
-
if (process.env.
|
|
1419
|
+
if (process.env.RNX_HOME && isSootsimDevCheckout() && !readActiveRuntime()) {
|
|
1420
1420
|
return
|
|
1421
1421
|
}
|
|
1422
1422
|
void this.runRuntimeUpdate('startup')
|
|
@@ -1434,7 +1434,7 @@ export class SootSimBridgeHost {
|
|
|
1434
1434
|
if (reason === 'startup') {
|
|
1435
1435
|
process.stderr.write('rnx: checking for runtime updates…\n')
|
|
1436
1436
|
}
|
|
1437
|
-
const result = await
|
|
1437
|
+
const result = await rnxRuntime.updateToLatest({
|
|
1438
1438
|
protectVersions: this.connectedRuntimeVersions(),
|
|
1439
1439
|
})
|
|
1440
1440
|
if (!result.updated || !result.latestVersion) {
|
package/src/metro-plugin.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// rnx metro plugin for opt-in dev shell and production bundle integration.
|
|
2
|
-
// shell assets come from an engine runtime under ~/.
|
|
2
|
+
// shell assets come from an engine runtime under ~/.rnx/runtimes/, fetched
|
|
3
3
|
// by `rnx runtime install`. ordinary localhost requests
|
|
4
4
|
// follow active; a version-owned localhost origin stays on its exact directory
|
|
5
5
|
// when active changes, so one loaded shell cannot mix runtime chunk trees.
|
|
@@ -423,7 +423,7 @@ export function withRNX<T extends Record<string, unknown>>(
|
|
|
423
423
|
},
|
|
424
424
|
}
|
|
425
425
|
|
|
426
|
-
if (appName && !process.env.CI && !process.env.
|
|
426
|
+
if (appName && !process.env.CI && !process.env.RNX_NO_OPEN) {
|
|
427
427
|
void openRnxDesktopWhenMetroIsReady({
|
|
428
428
|
port,
|
|
429
429
|
bundleUrl: resolveRnxDesktopLaunchTarget(port, bundleUrl),
|
package/src/profiles.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'fs'
|
|
2
2
|
import path from 'path'
|
|
3
|
-
import { electronUserDataDir,
|
|
3
|
+
import { electronUserDataDir, ensureRnxHome, profilesDir } from './home-paths'
|
|
4
4
|
|
|
5
5
|
export const DEFAULT_PROFILE_ID = 'default'
|
|
6
6
|
const PROFILE_INDEX_FILE = 'profiles.json'
|
|
@@ -105,7 +105,7 @@ function withDefault(index: ProfileIndex): ProfileIndex {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
function writeIndex(index: ProfileIndex): ProfileIndex {
|
|
108
|
-
|
|
108
|
+
ensureRnxHome()
|
|
109
109
|
const next = withDefault(index)
|
|
110
110
|
const tmp = `${profileIndexPath()}.tmp`
|
|
111
111
|
fs.writeFileSync(tmp, `${JSON.stringify(next, null, 2)}\n`, 'utf8')
|
package/src/runtime-assets.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// helpers for serving the installed sootsim engine runtime from framework
|
|
2
2
|
// dev servers. the runtime is managed by `sootsim runtime install` and lives
|
|
3
|
-
// under ~/.
|
|
3
|
+
// under ~/.rnx/runtimes/<version>.
|
|
4
4
|
|
|
5
5
|
import fs from 'fs'
|
|
6
6
|
import path from 'path'
|
|
@@ -20,13 +20,13 @@ export const SOOTSIM_RUNTIME_MISSING_MESSAGE =
|
|
|
20
20
|
// boundary, not a preference or a runtime fallback chain — the check is
|
|
21
21
|
// structural (the monorepo layout is present next to this module) and
|
|
22
22
|
// deterministic (the dev build's files exist). it exists because the daemon and
|
|
23
|
-
// the /__soot plugin otherwise serve ~/.
|
|
23
|
+
// the /__soot plugin otherwise serve ~/.rnx/runtimes/<active>, a PUBLISHED
|
|
24
24
|
// runtime that `bun dev` never refreshes, so local engine edits are invisible
|
|
25
25
|
// until a manual publish — the silent trap that cost a full night of
|
|
26
26
|
// already-fixed bugs re-reproducing.
|
|
27
27
|
//
|
|
28
28
|
// the isolated CI headless path (scripts/local-publish-runtime.sh) sets
|
|
29
|
-
//
|
|
29
|
+
// RNX_HOME to a dedicated dir precisely to validate the published-runtime
|
|
30
30
|
// code path; keying off that EXISTING isolation env keeps it (and packaged
|
|
31
31
|
// electron with a custom home) on the installed runtime.
|
|
32
32
|
let _monorepoRootCache: string | null | undefined
|
|
@@ -52,16 +52,16 @@ function findMonorepoRoot(): string | null {
|
|
|
52
52
|
|
|
53
53
|
/** the fresh dev-stack engine build to serve when running inside the Contrast
|
|
54
54
|
* monorepo dev checkout, or null when the installed runtime should serve
|
|
55
|
-
* (published CLI, packaged electron, or an isolated
|
|
55
|
+
* (published CLI, packaged electron, or an isolated RNX_HOME). */
|
|
56
56
|
export function resolveDevCheckoutRuntimeRoot(): string | null {
|
|
57
57
|
// an explicit home that has a STAGED/active runtime is the isolation the
|
|
58
58
|
// CI/local-publish path sets up to validate the installed-runtime code path —
|
|
59
59
|
// honor that staged runtime. an explicit home with NO active runtime is just
|
|
60
|
-
// an isolated dev daemon (own lockfile, doesn't clobber ~/.
|
|
61
|
-
// still wants the dev build; and the default home (
|
|
60
|
+
// an isolated dev daemon (own lockfile, doesn't clobber ~/.rnx), which
|
|
61
|
+
// still wants the dev build; and the default home (RNX_HOME unset) always
|
|
62
62
|
// does. keying on "explicit home + a runtime deliberately staged there" keeps
|
|
63
63
|
// it structural, not a bespoke toggle.
|
|
64
|
-
if (process.env.
|
|
64
|
+
if (process.env.RNX_HOME && readActiveRuntime()) return null
|
|
65
65
|
const root = findMonorepoRoot()
|
|
66
66
|
if (!root) return null
|
|
67
67
|
const devBuild = path.join(root, 'public/sootsim')
|
package/src/runtime-delivery.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
//
|
|
1
|
+
// rnx's binding of the shared runtime-delivery machinery.
|
|
2
2
|
//
|
|
3
3
|
// the machinery itself (hosted manifest, sha256-verified tarballs, channels,
|
|
4
4
|
// channel resolution, and auto-update) lives in @contrast/runtime-delivery and
|
|
5
|
-
// knows nothing about
|
|
6
|
-
//
|
|
5
|
+
// knows nothing about rnx. this file supplies rnx's identity, public env
|
|
6
|
+
// overrides, and the contrast.dev/runtimes hosting layout.
|
|
7
7
|
//
|
|
8
8
|
// @contrast/runtime-delivery is an internal workspace package that is never
|
|
9
9
|
// published, so both the CLI bundle and dist-lib inline it (see the `alias`
|
|
@@ -14,7 +14,7 @@ import { createRuntimeDelivery, type RuntimeProduct } from '@contrast/runtime-de
|
|
|
14
14
|
import {
|
|
15
15
|
cacheDir,
|
|
16
16
|
configFilePath,
|
|
17
|
-
|
|
17
|
+
ensureRnxHome,
|
|
18
18
|
readActiveRuntime,
|
|
19
19
|
runtimeDir,
|
|
20
20
|
runtimesDir,
|
|
@@ -25,12 +25,12 @@ import { rnxPublicBrand } from './public-brand.ts'
|
|
|
25
25
|
export const DEFAULT_RUNTIME_CDN_ORIGIN = 'https://contrast.dev'
|
|
26
26
|
|
|
27
27
|
/** the official curated changelog and the machine-readable release feed. the
|
|
28
|
-
*
|
|
29
|
-
export const
|
|
30
|
-
export const
|
|
28
|
+
* rnx site is static, so its /api traffic is owned by contrast.dev. */
|
|
29
|
+
export const RNX_CHANGELOG_URL = `${rnxPublicBrand.origin}/changelog`
|
|
30
|
+
export const RNX_CHANGELOG_API_URL = 'https://contrast.dev/api/changelog/sootsim'
|
|
31
31
|
|
|
32
|
-
export const
|
|
33
|
-
id: '
|
|
32
|
+
export const RNX_RUNTIME_PRODUCT: RuntimeProduct = {
|
|
33
|
+
id: 'rnx',
|
|
34
34
|
defaultCdnOrigin: DEFAULT_RUNTIME_CDN_ORIGIN,
|
|
35
35
|
manifestPath: '/runtimes/manifest.json',
|
|
36
36
|
tarballPath: (version) => `/runtimes/sootsim-runtime-${version}.tar.gz`,
|
|
@@ -39,10 +39,10 @@ export const SOOTSIM_RUNTIME_PRODUCT: RuntimeProduct = {
|
|
|
39
39
|
// vite/metro plugins serve, so its absence means the tarball is not one.
|
|
40
40
|
installedMarker: 'index.html',
|
|
41
41
|
env: {
|
|
42
|
-
cdnOrigin: '
|
|
43
|
-
channel: '
|
|
42
|
+
cdnOrigin: 'RNX_CDN_ORIGIN',
|
|
43
|
+
channel: 'RNX_RUNTIME_CHANNEL',
|
|
44
44
|
},
|
|
45
|
-
ensureHome:
|
|
45
|
+
ensureHome: ensureRnxHome,
|
|
46
46
|
configFile: configFilePath,
|
|
47
47
|
runtimesDir,
|
|
48
48
|
runtimeDir,
|
|
@@ -51,4 +51,4 @@ export const SOOTSIM_RUNTIME_PRODUCT: RuntimeProduct = {
|
|
|
51
51
|
writeActiveRuntime,
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
export const
|
|
54
|
+
export const rnxRuntime = createRuntimeDelivery(RNX_RUNTIME_PRODUCT)
|
|
@@ -244,7 +244,7 @@ export async function runScreenshotsPlanFromExistingRaw(
|
|
|
244
244
|
plan.capture.rawDir = rawDir
|
|
245
245
|
plan.capture.flowPath = null
|
|
246
246
|
plan.capture.fromDir = rawDir
|
|
247
|
-
const framedDir = path.join(tmpdir(), '
|
|
247
|
+
const framedDir = path.join(tmpdir(), 'rnx-screenshots-framed')
|
|
248
248
|
plan.capture.framedDir = framedDir
|
|
249
249
|
const framedSources = await buildFramedSources(plan)
|
|
250
250
|
const capture = writeCaptureManifest(plan, framedSources, plan.deviceModel)
|
|
@@ -246,7 +246,7 @@ export function loadScreenshotsPlan(planPath: string): NormalizedScreenshotsPlan
|
|
|
246
246
|
const deviceModel = readDeviceModel(root.device, null)
|
|
247
247
|
const captureOutDir = resolvePlanPath(
|
|
248
248
|
planDir,
|
|
249
|
-
readString(capture.out, path.join('.
|
|
249
|
+
readString(capture.out, path.join('.rnx', 'screenshots', 'capture')),
|
|
250
250
|
)
|
|
251
251
|
const captureFrom = readOptionalString(capture.from)
|
|
252
252
|
const flowPath = readOptionalString(capture.flow)
|
|
@@ -335,7 +335,7 @@ export function loadScreenshotsPlan(planPath: string): NormalizedScreenshotsPlan
|
|
|
335
335
|
compose: {
|
|
336
336
|
outDir: resolvePlanPath(
|
|
337
337
|
planDir,
|
|
338
|
-
readString(compose.out, path.join('.
|
|
338
|
+
readString(compose.out, path.join('.rnx', 'screenshots', 'exports')),
|
|
339
339
|
),
|
|
340
340
|
locale: readString(compose.locale, 'en'),
|
|
341
341
|
canvases: normalizeCanvasList(compose.canvases),
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// built-in skill: accessibility audit
|
|
2
2
|
|
|
3
3
|
import { launchReapedChrome } from '../../../../../scripts/lib/reap-browser'
|
|
4
|
-
import type {
|
|
4
|
+
import type { RNXSkill } from '../types'
|
|
5
5
|
|
|
6
|
-
export const skill:
|
|
6
|
+
export const skill: RNXSkill = {
|
|
7
7
|
name: 'a11y-review',
|
|
8
8
|
description: 'Check the app for accessibility issues',
|
|
9
9
|
type: 'review',
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// built-in skill: package compatibility check
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { RNXSkill } from '../types'
|
|
4
4
|
|
|
5
|
-
export const skill:
|
|
5
|
+
export const skill: RNXSkill = {
|
|
6
6
|
name: 'compat-check',
|
|
7
7
|
description: 'Check package compatibility with rnx',
|
|
8
8
|
type: 'review',
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// built-in skill: run Maestro tests against the app
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { RNXSkill } from '../types'
|
|
4
4
|
|
|
5
5
|
function sleep(ms: number) {
|
|
6
6
|
return new Promise((resolve) => setTimeout(resolve, ms))
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
export const skill:
|
|
9
|
+
export const skill: RNXSkill = {
|
|
10
10
|
name: 'maestro-test',
|
|
11
11
|
description: 'Run Maestro YAML tests against the app',
|
|
12
12
|
type: 'testing',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// built-in skill: performance profiling
|
|
2
2
|
|
|
3
3
|
import { launchReapedChrome } from '../../../../../scripts/lib/reap-browser'
|
|
4
|
-
import type {
|
|
4
|
+
import type { RNXSkill } from '../types'
|
|
5
5
|
|
|
6
6
|
interface OverlayProfile {
|
|
7
7
|
syncCount?: number
|
|
@@ -9,7 +9,7 @@ interface OverlayProfile {
|
|
|
9
9
|
[key: string]: unknown
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export const skill:
|
|
12
|
+
export const skill: RNXSkill = {
|
|
13
13
|
name: 'perf-profile',
|
|
14
14
|
description: 'Profile render performance of the app',
|
|
15
15
|
type: 'performance',
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// built-in skill: capture all screens in light/dark mode
|
|
2
2
|
|
|
3
3
|
import { launchReapedChrome } from '../../../../../scripts/lib/reap-browser'
|
|
4
|
-
import type {
|
|
4
|
+
import type { RNXSkill } from '../types'
|
|
5
5
|
|
|
6
|
-
export const skill:
|
|
6
|
+
export const skill: RNXSkill = {
|
|
7
7
|
name: 'screenshot-all',
|
|
8
8
|
description: 'Capture screenshots of all screens in the app',
|
|
9
9
|
type: 'screenshot',
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// built-in skill: visual diff against baselines
|
|
2
2
|
|
|
3
3
|
import { launchReapedChrome } from '../../../../../scripts/lib/reap-browser'
|
|
4
|
-
import type {
|
|
4
|
+
import type { RNXSkill } from '../types'
|
|
5
5
|
|
|
6
|
-
export const skill:
|
|
6
|
+
export const skill: RNXSkill = {
|
|
7
7
|
name: 'visual-diff',
|
|
8
8
|
description: 'Compare current rendering against baseline screenshots',
|
|
9
9
|
type: 'review',
|
package/src/skills/registry.ts
CHANGED
|
@@ -8,9 +8,9 @@ import { skill as maestroTestSkill } from './builtin/maestro-test'
|
|
|
8
8
|
import { skill as perfProfileSkill } from './builtin/perf-profile'
|
|
9
9
|
import { skill as screenshotAllSkill } from './builtin/screenshot-all'
|
|
10
10
|
import { skill as visualDiffSkill } from './builtin/visual-diff'
|
|
11
|
-
import type {
|
|
11
|
+
import type { RNXSkill, SkillContext } from './types'
|
|
12
12
|
|
|
13
|
-
const _skills: Map<string,
|
|
13
|
+
const _skills: Map<string, RNXSkill> = new Map()
|
|
14
14
|
const BUILTIN_SKILLS = [
|
|
15
15
|
a11yReviewSkill,
|
|
16
16
|
compatCheckSkill,
|
|
@@ -21,20 +21,20 @@ const BUILTIN_SKILLS = [
|
|
|
21
21
|
]
|
|
22
22
|
|
|
23
23
|
export const skillRegistry = {
|
|
24
|
-
register(skill:
|
|
24
|
+
register(skill: RNXSkill) {
|
|
25
25
|
_skills.set(skill.name, skill)
|
|
26
26
|
},
|
|
27
27
|
|
|
28
|
-
get(name: string):
|
|
28
|
+
get(name: string): RNXSkill | undefined {
|
|
29
29
|
return _skills.get(name)
|
|
30
30
|
},
|
|
31
31
|
|
|
32
|
-
listAll():
|
|
32
|
+
listAll(): RNXSkill[] {
|
|
33
33
|
return Array.from(_skills.values())
|
|
34
34
|
},
|
|
35
35
|
|
|
36
36
|
// match skills by natural language query against triggers
|
|
37
|
-
match(query: string):
|
|
37
|
+
match(query: string): RNXSkill[] {
|
|
38
38
|
const q = query.toLowerCase()
|
|
39
39
|
return this.listAll().filter((skill) =>
|
|
40
40
|
skill.triggers.some((trigger) => q.includes(trigger.toLowerCase())),
|
|
@@ -48,9 +48,9 @@ export const skillRegistry = {
|
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
50
|
|
|
51
|
-
// load skills from a project manifest (
|
|
51
|
+
// load skills from a project manifest (rnx-skills.json)
|
|
52
52
|
async loadFromManifest(projectDir: string) {
|
|
53
|
-
const manifestPath = path.join(projectDir, '
|
|
53
|
+
const manifestPath = path.join(projectDir, 'rnx-skills.json')
|
|
54
54
|
if (!fs.existsSync(manifestPath)) return
|
|
55
55
|
|
|
56
56
|
try {
|
package/src/skills/types.ts
CHANGED
package/src/vite-plugin-one.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// sootsim plugin for One/Vite — serves the installed sootsim runtime at /__soot/
|
|
2
|
-
// from ~/.
|
|
2
|
+
// from ~/.rnx/runtimes/<version>. version-owned localhost origins remain
|
|
3
3
|
// bound to that directory across an active-runtime update.
|
|
4
4
|
//
|
|
5
5
|
// usage in vite.config.ts:
|
|
@@ -36,7 +36,7 @@ export interface RnxPluginOptions {
|
|
|
36
36
|
// disable sootsim
|
|
37
37
|
enabled?: boolean
|
|
38
38
|
// launch the sootsim simulator loading this server's bundle once the dev
|
|
39
|
-
// server is listening. skipped when CI or
|
|
39
|
+
// server is listening. skipped when CI or RNX_NO_OPEN is set.
|
|
40
40
|
open?: RnxDesktopOpenOption
|
|
41
41
|
}
|
|
42
42
|
|
|
@@ -220,7 +220,7 @@ export function rnxPlugin(options: RnxPluginOptions = {}): Plugin {
|
|
|
220
220
|
const sootsimUrl = `http://localhost:${port}${prefix}/`
|
|
221
221
|
console.log(`[rnx] serving at ${sootsimUrl}`)
|
|
222
222
|
|
|
223
|
-
if (appName && !process.env.CI && !process.env.
|
|
223
|
+
if (appName && !process.env.CI && !process.env.RNX_NO_OPEN) {
|
|
224
224
|
server.httpServer?.once('listening', () => {
|
|
225
225
|
const openPort = listeningPort()
|
|
226
226
|
launchRnxDesktop(
|
package/src/vite-plugin.ts
CHANGED
|
@@ -748,7 +748,15 @@ const viteBridgeProcesses = (globalThis.__sootsimViteBridgeProcesses ??= new Map
|
|
|
748
748
|
// start WS bridge server for debug CLI connectivity. exported so shell
|
|
749
749
|
// vite can install it standalone (engine builds via `vite build --watch`,
|
|
750
750
|
// which doesn't fire configureServer — the bridge has to run on shell).
|
|
751
|
-
export function wsBridgePlugin(): Plugin {
|
|
751
|
+
export function wsBridgePlugin(options: { ownedBridgePort?: number } = {}): Plugin {
|
|
752
|
+
if (
|
|
753
|
+
options.ownedBridgePort !== undefined &&
|
|
754
|
+
(!Number.isInteger(options.ownedBridgePort) ||
|
|
755
|
+
options.ownedBridgePort <= 0 ||
|
|
756
|
+
options.ownedBridgePort > 65_535)
|
|
757
|
+
) {
|
|
758
|
+
throw new Error(`invalid externally owned bridge port: ${options.ownedBridgePort}`)
|
|
759
|
+
}
|
|
752
760
|
const owner = {}
|
|
753
761
|
// the port the bridge ACTUALLY bound, which is not necessarily the one it
|
|
754
762
|
// asked for: the host scans forward from its preferred port on EADDRINUSE.
|
|
@@ -756,7 +764,12 @@ export function wsBridgePlugin(): Plugin {
|
|
|
756
764
|
// the shell's http port instead, any box where 7668 was already taken sent
|
|
757
765
|
// the page dialing a port nobody listens on, and the only symptom was a
|
|
758
766
|
// websocket console error during boot.
|
|
759
|
-
|
|
767
|
+
// a parent that already owns a bridge supplies its receipt here. the shell
|
|
768
|
+
// publishes that exact port and never starts a competing development bridge.
|
|
769
|
+
let boundPort: Promise<number | null> | null =
|
|
770
|
+
options.ownedBridgePort === undefined
|
|
771
|
+
? null
|
|
772
|
+
: Promise.resolve(options.ownedBridgePort)
|
|
760
773
|
return {
|
|
761
774
|
name: 'sootsim-ws-bridge',
|
|
762
775
|
apply: 'serve',
|
package/dist-cli/bin.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/*! rnx v0.1.376 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
3
|
-
import { createRequire as __sootsimCreateRequire } from 'node:module'
|
|
4
|
-
var require = __sootsimCreateRequire(import.meta.url)
|
|
5
|
-
import{a as g,b as f}from"./chunks/chunk-LQMUA5IY.js";import{a as h}from"./chunks/chunk-TH2UFGVP.js";import{a as m}from"./chunks/chunk-5YZYDEMI.js";import"./chunks/chunk-ZSSG7OR7.js";function k(a){let t=a instanceof Error?a.message:String(a);(/^command timed out after \d+s$/.test(t)||t.startsWith("sim disconnected:")||t.startsWith("bridge never reconnected")||t.startsWith("multiple sims are connected:")||t.startsWith("saved sim ")||t.startsWith("no sim connected with id ")||t.startsWith("could not connect to ws://")||t.startsWith("rnx bridge daemon is not running")||t.startsWith("rnx bridge lockfile is fresh")||t.startsWith("rnx bridge exited before becoming ready")||t.startsWith(`${m.commandName} open: requested bridge port`)||t.startsWith("background daemon setup is unavailable")||t.startsWith("rnx bridge did not start within"))&&!process.env.SOOTSIM_VERBOSE&&(process.stderr.write(` ${t}
|
|
6
|
-
`),process.exit(1)),a instanceof Error&&a.stack?process.stderr.write(`${a.stack}
|
|
7
|
-
`):process.stderr.write(`${t}
|
|
8
|
-
`),process.exit(1)}process.on("unhandledRejection",k);process.on("uncaughtException",k);var v=typeof __SOOTSIM_STANDALONE__<"u"&&__SOOTSIM_STANDALONE__,C=new Set(["desktop"]);function $(a){!v||!C.has(a)||(process.stderr.write(` ${m.commandName} ${a} isn't available in the standalone binary \u2014
|
|
9
|
-
it needs vite / electron / playwright from a project's node_modules.
|
|
10
|
-
run the npm package instead:
|
|
11
|
-
${m.commandName} ${a}
|
|
12
|
-
`),process.exit(1))}var e=f(process.argv);if(!e.command&&e.commandArgs.length>0){let{resolveHiddenRuntimeAlias:a}=await import("./chunks/hidden-runtime-alias-HHT2C7WE.js");e=a(e)}var _=e.command==="cleanup"&&e.commandArgs.length===1&&e.commandArgs[0]==="--automatic-worker",x=!e.command&&e.commandArgs.length===0;if(!_&&!x&&!e.help&&!e.version&&e.command!=="config"&&e.command!=="setup"&&e.command!=="telemetry"){let{ensurePrivacyChoice:a}=await import("./chunks/privacy-57UOTB5J.js");await a({prompt:!0})}if(e.command!=="serve"&&e.command!=="daemon"){let{consumeRuntimeUpgradeNotice:a}=await import("./chunks/home-paths-KTPGCPMS.js"),t=a();t&&process.stderr.write(` ${m.name} engine upgraded to v${t.to}`+(t.from?` (from v${t.from})`:"")+` \xB7 what's new: ${m.origin}/changelog
|
|
13
|
-
`)}var b=!1;async function S(){if(!b&&(b=!0,!(e.command==="cleanup"||e.command==="serve"||e.command==="agent-wrapper"||e.command==="daemon"&&e.commandArgs[0]==="uninstall")))try{let{shouldSkipAutomaticSootsimCleanup:a}=await import("./chunks/disk-cleanup-VURWJYQV.js");if(a())return;let{spawn:t}=await import("node:child_process"),r=["cleanup","--automatic-worker"],d=process.argv[1],p=v?t(process.execPath,r,{detached:!0,stdio:["ignore","ignore","inherit"],env:process.env}):d?t(process.execPath,[d,...r],{detached:!0,stdio:["ignore","ignore","inherit"],env:process.env}):t(m.commandName,r,{detached:!0,stdio:["ignore","ignore","inherit"],env:process.env});p.once("error",w=>{process.stderr.write(` ${m.name} automatic cleanup will retry on the next run: ${w.message}
|
|
14
|
-
`)}),p.unref()}catch(a){process.stderr.write(` ${m.name} automatic cleanup will retry on the next run: ${a instanceof Error?a.message:String(a)}
|
|
15
|
-
`)}}async function n(a){let{flushCliTelemetry:t}=await import("./chunks/telemetry-FBL3NAKB.js");await t(),await S(),process.exit(a)}if(e.version){let{getCliVersion:a}=await import("./chunks/cli-version-OBNR366V.js"),{IS_BETA:t,BETA_LABEL:r}=await import("./chunks/beta-5AO3SJB7.js"),d=t?` \xB7 ${r}`:"";console.log(`${m.commandName} v${a()}${d}`);let{readActiveRuntime:p}=await import("./chunks/home-paths-KTPGCPMS.js"),w=p();console.log(w?`runtime v${w}`:"runtime not installed"),await n(0)}if(e.help&&!e.command){let{printHelp:a}=await import("./chunks/help-34CJMQY2.js");a(),await n(0)}var o=e.globalFlags.port,c=e.verbose,u=e.globalFlags.device,l=e.globalFlags.theme,E=e.globalFlags.driver,O=e.globalFlags.headless===!0,A=e.globalFlags.sim??e.globalFlags.session??e.globalFlags.tab,i=A?["--sim",A,...e.commandArgs]:e.commandArgs;if(u||l){let{settingsStore:a}=await import("./chunks/store-XMCUA45G.js"),t={};u&&(t.deviceModel=u),l&&(t.colorScheme=l),a.apply(t)}if(!e.command&&e.commandArgs.length===0){let{runWelcome:a}=await import("./chunks/welcome-QYGSQCWQ.js");await n(await a())}var s=e.command??"";if(!s){if(e.commandArgs.length>0){let t=e.commandArgs.find(r=>!r.startsWith("-"))??e.commandArgs[0];console.error(` unknown command: ${t}`),console.error(` run \`${m.commandName} --help\` to see the full surface.`),await n(1)}let{printHelp:a}=await import("./chunks/help-34CJMQY2.js");a(),await n(0)}if(e.help||e.commandArgs.includes("--help")||e.commandArgs.includes("-h")){if(s==="skill"){let{runSkill:r}=await import("./chunks/skills-EYXWBRNQ.js");await r(e.commandArgs),await n(0)}if(s==="state"){let{runState:r}=await import("./chunks/state-REJ7W6K3.js");await n(await r(i,{port:o}))}if(s==="reset"){let{runReset:r}=await import("./chunks/reset-H5NBFE5U.js");await n(await r(i,{port:o}))}let a=s==="do"||s==="get"||s==="debug"||s==="shell"||s==="perf"||s==="wait",t=e.commandArgs.find(r=>!r.startsWith("-"));if(!(s==="shell"||s==="perf"))if(a&&!t){let{printGroupHelp:r}=await import("./chunks/help-34CJMQY2.js");r(s)&&await n(0)}else{let{printCommandHelp:r}=await import("./chunks/help-34CJMQY2.js");r(a&&t?t:s,{prefer:a&&t?"verb":"command",group:a&&t?s:void 0}),await n(0)}}$(s);try{if(g.has(s)){if(s==="do"){let{hasDoChain:t,runDoChain:r}=await import("./chunks/do-chain-DJ4UQC7A.js");t(i)&&await n(await r(i,{port:o}))}let{runInspect:a}=await import("./chunks/inspect-JF5WYJRD.js");await a([s,...i],{port:o,verbose:c})}else switch(s){case"assert":{let{runAssert:a}=await import("./chunks/assert-IXOLVO5Z.js");await a(e.commandArgs);break}case"detox":{let{runDetox:a}=await import("./chunks/detox-C2ILVBEC.js");await a(e.commandArgs,{port:o,verbose:c});break}case"maestro":{let{runMaestro:a}=await import("./chunks/maestro-W46QCF77.js"),t=await a(i,{port:o,verbose:c});await n(typeof t=="number"?t:0)}case"record":{let{runRecord:a}=await import("./chunks/record-VXG37P7U.js");await a(i,{port:o,verbose:c});break}case"film":{let{runFilm:a}=await import("./chunks/film-DCPS7EID.js"),t=await a(i,{port:o,verbose:c});await n(typeof t=="number"?t:0)}case"storage":{let{runStorage:a}=await import("./chunks/storage-CFMDHI3V.js"),t=await a(i,{port:o,verbose:c});await n(typeof t=="number"?t:0)}case"state":{let{runState:a}=await import("./chunks/state-REJ7W6K3.js"),t=await a(i,{port:o});await n(t)}case"reset":{let{runReset:a}=await import("./chunks/reset-H5NBFE5U.js"),t=await a(i,{port:o});await n(t)}case"perf":{let{runPerf:a}=await import("./chunks/perf-YVT2WXT4.js"),t=await a(i,{port:o,verbose:c});await n(typeof t=="number"?t:0)}case"screenshot":{let{runScreenshotCommand:a}=await import("./chunks/screenshot-command-AN56TTG7.js"),t=await a(i,{port:o,verbose:c});await n(typeof t=="number"?t:0)}case"camera":{let{runCamera:a}=await import("./chunks/camera-FNJVFCDQ.js"),t=await a(i,{port:o});await n(typeof t=="number"?t:0)}case"mode":{let{runMode:a}=await import("./chunks/mode-ZEDZK7R7.js");await a(i,{port:o,verbose:c});break}case"permissions":{let{runPermissions:a}=await import("./chunks/permissions-L7VVDHFP.js"),t=await a(i,{port:o,verbose:c});await n(t)}case"debug":{let{runDebug:a}=await import("./chunks/debug-GUVAK2KR.js");await a(i,{port:o,verbose:c});break}case"timeline":{let{runTimeline:a}=await import("./chunks/timeline-HMCHN5FO.js");await a(i,{port:o,verbose:c});break}case"what-happened":{let{runWhatHappened:a}=await import("./chunks/what-happened-YTOUK4LO.js");await a(i,{port:o,verbose:c});break}case"open":{let{runOpenCommand:a}=await import("./chunks/control-Z3FWA6BO.js");await a(i,{port:o});break}case"ios":case"android":{let{runPlatformCommand:a}=await import("./chunks/platform-7TJOU2FB.js"),t=await a(s,i,{port:o});await n(typeof t=="number"?t:0)}case"box":{let{runBox:a}=await import("./chunks/box-ZHM66L6K.js");await n(await a(i,{port:o,verbose:c}))}case"use":{let{runUseCommand:a}=await import("./chunks/control-Z3FWA6BO.js");await a(i,{port:o});break}case"claim":{let{runClaimCommand:a}=await import("./chunks/control-Z3FWA6BO.js");await a(i,{port:o});break}case"close":{let{runCloseCommand:a}=await import("./chunks/control-Z3FWA6BO.js");await a(i,{port:o});break}case"device":{let{runDeviceCommand:a}=await import("./chunks/device-NXIQQJWR.js");await a(i,{port:o});break}case"compat":{let{runCompat:a}=await import("./chunks/compat-SHMFSKU7.js");await a(e.commandArgs);break}case"report-issue":{let{runReportIssue:a}=await import("./chunks/report-issue-WNNOBZHC.js"),t=await a(e.commandArgs);await n(t)}case"desktop":{let{runDesktop:a}=await import("./chunks/desktop-OOP2PTKP.js");await a(e.commandArgs,{port:o,device:u});break}case"login":{let{runLogin:a}=await import("./chunks/login-TTJAOI2Q.js");await a(e.commandArgs);break}case"logout":{let{runLogout:a}=await import("./chunks/logout-ERAQ6SKW.js");await a();break}case"auth":{let{runAuth:a}=await import("./chunks/auth-KFMFB6FU.js");await a(e.commandArgs);break}case"setup":{let{runSetup:a}=await import("./chunks/setup-UA2HLD7S.js");await a(e.commandArgs);break}case"serve":{let{runServe:a}=await import("./chunks/serve-GLYO5Q7J.js");await a(e.commandArgs,{port:o});break}case"daemon":{let{runDaemon:a}=await import("./chunks/daemon-RSVYSC65.js");await a(e.commandArgs,{port:o});break}case"runtime":{let{runRuntime:a}=await import("./chunks/runtime-QU2NIF2K.js");await a(e.commandArgs);break}case"upgrade":{let{runUpgrade:a}=await import("./chunks/upgrade-2QSPAA3P.js");await a(e.commandArgs);break}case"version":{let{runVersion:a}=await import("./chunks/version-IOA6QFGB.js");await a(e.commandArgs);break}case"agent":{let{runAgentCommand:a}=await import("./chunks/agent-H42FCKFF.js"),t=await a(e.commandArgs);await n(t)}case"agent-wrapper":{let{runAgentWrapper:a}=await import("./chunks/agent-wrapper-BBZKTZS6.js"),t=await a(e.commandArgs);await n(t)}case"skill":{let{runSkill:a}=await import("./chunks/skills-EYXWBRNQ.js");await a(e.commandArgs);break}case"app-fonts":{let{runAppFonts:a}=await import("./chunks/app-fonts-43VXIKF4.js");await a(e.commandArgs);break}case"config":{let{runConfig:a}=await import("./chunks/config-TPEAEUJ2.js");await a(e.commandArgs);break}case"cleanup":{let{runCleanup:a}=await import("./chunks/cleanup-MLOK2OZA.js"),t=await a(e.commandArgs);await n(t)}default:console.error(` unknown command: ${s}`),console.error(` run \`${m.commandName} --help\` to see the full surface.`),await n(1)}}catch(a){throw a instanceof h&&await n(a.code),a}await S();
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/*! rnx v0.1.376 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import { createRequire as __sootsimCreateRequire } from 'node:module'
|
|
3
|
-
var require = __sootsimCreateRequire(import.meta.url)
|
|
4
|
-
import{a as b,b as E,c as A,d as l,e as S,g as x,h as j,j as T,n as I,o as k,p as D,q as g,r as O,s as C}from"./chunk-NORLYTTO.js";import"./chunk-XCDNVNP3.js";import{c as $}from"./chunk-LC3QRIRB.js";import"./chunk-MLBZZHOY.js";import"./chunk-VQDYFFIG.js";import"./chunk-TEESPOYR.js";import"./chunk-DOVBJBVD.js";import"./chunk-DGJMIVZM.js";import"./chunk-CWCQP53A.js";import"./chunk-DGX3MN65.js";import"./chunk-AFOVILIL.js";import{j as y}from"./chunk-QRDF33WD.js";import"./chunk-XSVILA4Z.js";import"./chunk-5YZYDEMI.js";import"./chunk-ZSSG7OR7.js";import w from"node:fs";import d from"node:path";import{spawn as _}from"node:child_process";import F from"node:net";import{WebSocket as R}from"ws";var c=class extends Error{code;constructor(e,t){super(e),this.name="AgentDaemonError",this.code=t}},f=class{ws;port;commandTimeoutMs;ready;closed=!1;nextId=1;pending=new Map;eventListeners=new Set;statusListeners=new Set;disconnectListeners=new Set;constructor(e={}){this.port=e.port??7668,this.commandTimeoutMs=e.commandTimeoutMs??15e3,this.ws=new R(`ws://localhost:${this.port}`),this.ready=new Promise((t,r)=>{let s=()=>{this.ws.off("error",o),t()},o=i=>{this.ws.off("open",s),r(new c(`could not connect to rnx daemon on port ${this.port}: ${i.message}`,"NO_DAEMON"))};this.ws.once("open",s),this.ws.once("error",o)}),this.ws.on("message",t=>this.handleMessage(t)),this.ws.on("close",()=>this.handleClose()),this.ws.on("error",()=>{})}async waitReady(){return this.ready}async listProjects(){return this.send("agent:list-projects")}async upsertProject(e){return this.send("agent:upsert-project",{input:e})}async deleteProject(e){return this.send("agent:delete-project",{projectId:e})}async autoAttachForUrl(e){return this.send("agent:auto-attach-for-url",{input:e})}async listSessions(e){return this.send("agent:list-sessions",{projectId:e})}async startSession(e){return this.send("agent:start-session",{input:e})}async sendPrompt(e,t){return this.send("agent:send-prompt",{sessionId:e,prompt:t})}async sendClaimedPrompt(e,t){return this.send("agent:send-claimed-prompt",{simId:e,prompt:t})}async endSession(e){return this.send("agent:end-session",{sessionId:e})}async getTranscript(e){return this.send("agent:get-transcript",{sessionId:e})}async getPaths(){return this.send("agent:get-paths")}async subscribeEvents(e){return this.send("agent:subscribe-events",{sessionId:e})}async unsubscribeEvents(e){return this.send("agent:unsubscribe-events",{sessionId:e})}onAgentEvent(e){return this.eventListeners.add(e),()=>this.eventListeners.delete(e)}onSessionStatusChange(e){return this.statusListeners.add(e),()=>this.statusListeners.delete(e)}onDisconnect(e){return this.disconnectListeners.add(e),()=>this.disconnectListeners.delete(e)}close(){if(!this.closed){this.closed=!0;try{this.ws.close()}catch{}}}async send(e,t={}){if(await this.ready,this.closed||this.ws.readyState!==R.OPEN)throw new c("daemon connection is closed","NO_DAEMON");let r=this.nextId++;return new Promise((s,o)=>{let i=setTimeout(()=>{this.pending.delete(r),o(new c(`${e} timed out after ${Math.round(this.commandTimeoutMs/1e3)}s`,"TIMEOUT"))},this.commandTimeoutMs);this.pending.set(r,{resolve:s,reject:o,timer:i});try{this.ws.send(JSON.stringify({id:r,type:e,...t}))}catch(a){clearTimeout(i),this.pending.delete(r),o(a instanceof Error?a:new Error(String(a)))}})}handleMessage(e){let t;try{t=JSON.parse(String(e))}catch{return}if(!t||typeof t!="object")return;if(t.type==="agent:event"){for(let s of this.eventListeners)try{s({sessionId:t.sessionId,event:t.event})}catch{}return}if(t.type==="agent:session-status"){for(let s of this.statusListeners)try{s(t.session)}catch{}return}if(typeof t.id!="number")return;let r=this.pending.get(t.id);r&&(this.pending.delete(t.id),clearTimeout(r.timer),t.error?r.reject(new c(t.error,t.code)):r.resolve(t.result))}handleClose(){if(!this.closed){this.closed=!0;for(let[,e]of this.pending)clearTimeout(e.timer),e.reject(new c("daemon disconnected","DISCONNECT"));this.pending.clear();for(let e of this.disconnectListeners)try{e()}catch{}}}};function M(n=7668,e=400){return new Promise(t=>{let r=new F.Socket,s=!1,o=i=>{s||(s=!0,r.destroy(),t(i))};r.setTimeout(e),r.once("connect",()=>o(!0)),r.once("timeout",()=>o(!1)),r.once("error",()=>o(!1)),r.connect(n,"127.0.0.1")})}async function B(n={}){let e=n.port??7668;if(await M(e))return{alreadyRunning:!0};if(y())throw new c(`no rnx bridge on port ${e}. run \`rnx daemon install\` to enable the faster background service, or \`rnx serve\` in another shell.`,"DEV_HOST_REFUSED");let{cmd:t,prefixArgs:r}=C(),s=[...r,"serve","--quiet"];e!==7668&&s.push("--port",String(e));let o=_(t,s,{detached:!0,stdio:"ignore",env:process.env,cwd:process.cwd()});o.unref();let i=Date.now()+(n.startupTimeoutMs??5e3);for(;Date.now()<i;){if(await M(e))return{alreadyRunning:!1,pid:o.pid};await new Promise(a=>setTimeout(a,100))}throw new c(`spawned rnx daemon on port ${e} but it did not come up in time. run \`rnx serve\` manually to diagnose.`,"SPAWN_TIMEOUT")}async function h(n={}){await B({port:n.port,startupTimeoutMs:n.startupTimeoutMs});let e=new f(n);try{await e.waitReady()}catch(t){throw e.close(),t}return e}async function ge(n){let[e,...t]=n;try{switch(e){case void 0:case"--help":case"-h":case"help":return L(),0;case"attach":return await W(t);case"projects":return await J();case"project":return await V(t);case"sessions":return await H(t);case"start":return await G(t);case"prompt":return await q(t);case"watch":return await K(t);case"transcript":return await z(t);case"end":return await Q(t);case"paths":return await Y();default:return process.stderr.write(`unknown agent subcommand: ${e}
|
|
5
|
-
`),L(),2}}catch(r){if(r instanceof c)return process.stderr.write(`${r.message}
|
|
6
|
-
`),1;throw r}}async function v(n){let e=await h({clientLabel:"sootsim-agent-cli"});try{return await n(e)}finally{e.close()}}function L(){$("agent")}function P(n,e){let t={},r=[];for(let s=0;s<n.length;s++){let o=n[s],i=e[o];i==="value"?(t[o]=n[s+1]??"",s++):i==="bool"?t[o]=!0:r.push(o)}return{flags:t,positional:r}}function U(n,e="codex"){return n==="codex"||n==="claude"?n:e}async function W(n){let{flags:e,positional:t}=P(n,{"--name":"value","--provider":"value"}),r=t[0];if(!r)return process.stderr.write(`usage: rnx agent attach <dir> [--name X] [--provider codex|claude]
|
|
7
|
-
`),2;let s=d.resolve(r);if(!w.existsSync(s))return process.stderr.write(`directory does not exist: ${s}
|
|
8
|
-
`),1;let o=A({cwd:s,name:e["--name"]||d.basename(s),preferredProvider:U(e["--provider"]),sourceRoots:[s]});return process.stdout.write(`\u2713 attached "${o.name}" (id: ${o.id})
|
|
9
|
-
cwd: ${o.cwd}
|
|
10
|
-
framework: ${o.framework}
|
|
11
|
-
preferred provider: ${o.preferredProvider}
|
|
12
|
-
`),0}async function J(){let n=[...S()].sort((t,r)=>r.updatedAt-t.updatedAt);if(n.length===0)return process.stdout.write("no attached projects yet. try `rnx agent attach <dir>`.\n"),0;let e=`${"ID".padEnd(18)} ${"NAME".padEnd(20)} ${"FRAMEWORK".padEnd(10)} ${"PROVIDER".padEnd(8)} ${"7D COST".padEnd(10)} CWD
|
|
13
|
-
`;process.stdout.write(e);for(let t of n){let r=x(t),s=r>0?`$${r.toFixed(2)}`:"\u2014";process.stdout.write(`${t.id.padEnd(18)} ${p(t.name,20).padEnd(20)} ${t.framework.padEnd(10)} ${t.preferredProvider.padEnd(8)} ${s.padEnd(10)} ${t.cwd}
|
|
14
|
-
`)}return 0}async function V(n){let[e,t]=n;if(e==="show"){if(!t)return process.stderr.write(`usage: rnx agent project show <id>
|
|
15
|
-
`),2;let r=l(t);return r?(process.stdout.write(JSON.stringify(r,null,2)+`
|
|
16
|
-
`),0):(process.stderr.write(`no project with id=${t}
|
|
17
|
-
`),1)}return e==="remove"?t?(j(t),process.stdout.write(`\u2713 removed project ${t}
|
|
18
|
-
`),0):(process.stderr.write(`usage: rnx agent project remove <id>
|
|
19
|
-
`),2):(process.stderr.write(`usage: rnx agent project [show|remove] <id>
|
|
20
|
-
`),2)}async function H(n){let{flags:e}=P(n,{"--project":"value","--all":"bool"}),t=e["--project"]||void 0,r=e["--all"]===!0,s=T(t);if(r||(s=s.filter(i=>i.status!=="ended")),s=s.sort((i,a)=>a.lastSeenAt-i.lastSeenAt),s.length===0)return process.stdout.write(r?`no sessions.
|
|
21
|
-
`:`no active sessions. pass --all to include ended.
|
|
22
|
-
`),0;let o=`${"SESSION".padEnd(26)} ${"PROJECT".padEnd(18)} ${"PROVIDER".padEnd(8)} ${"STATUS".padEnd(16)} ${"ALIVE".padEnd(5)} LAST PROMPT
|
|
23
|
-
`;process.stdout.write(o);for(let i of s){let a=O(i.wrapperPid,i.id)?"yes":"no",m=i.lastPrompt?p(i.lastPrompt,40):"";process.stdout.write(`${N(i.id).padEnd(26)} ${N(i.projectId).padEnd(18)} ${i.provider.padEnd(8)} ${i.status.padEnd(16)} ${a.padEnd(5)} ${m}
|
|
24
|
-
`)}return 0}async function G(n){let{flags:e,positional:t}=P(n,{"--provider":"value","--codex-bin":"value","--claude-bin":"value","--fresh-thread":"bool"}),r=t[0];if(!r)return process.stderr.write(`usage: rnx agent start <projectId> [--provider codex|claude] [--fresh-thread]
|
|
25
|
-
`),2;let s=await v(i=>i.startSession({projectId:r,provider:U(e["--provider"],void 0)||void 0,codexBin:e["--codex-bin"]||void 0,claudeBin:e["--claude-bin"]||void 0,freshThread:e["--fresh-thread"]===!0})),o=l(s.session.projectId);return process.stdout.write(`\u2713 session ${s.session.id} started
|
|
26
|
-
project: ${o.name} (${o.id})
|
|
27
|
-
provider: ${s.session.provider}
|
|
28
|
-
pid: ${s.wrapperPid}
|
|
29
|
-
prompt with: rnx agent prompt ${s.session.id} "<text>"
|
|
30
|
-
watch events: rnx agent watch ${s.session.id}
|
|
31
|
-
`),0}async function q(n){let[e,...t]=n,r=t.join(" ");return!e||!r?(process.stderr.write(`usage: rnx agent prompt <sessionId> "<text>"
|
|
32
|
-
`),2):(await v(s=>s.sendPrompt(e,{text:r})),process.stdout.write(`\u2713 prompt sent to ${e}
|
|
33
|
-
`),0)}async function K(n){let e=n[0];if(!e)return process.stderr.write(`usage: rnx agent watch <sessionId>
|
|
34
|
-
`),2;process.stdout.write(`watching ${e}
|
|
35
|
-
---
|
|
36
|
-
`);let t=await h({clientLabel:"sootsim-agent-watch"}),r,s=new Promise(a=>{r=a}),o=t.onAgentEvent(({sessionId:a,event:m})=>{a===e&&process.stdout.write(X(m)+`
|
|
37
|
-
`)}),i=t.onDisconnect(()=>{process.stderr.write(`
|
|
38
|
-
[rnx] daemon disconnected; exiting watch.
|
|
39
|
-
`),r(1)});try{await t.subscribeEvents(e)}catch(a){throw o(),i(),t.close(),a}return process.on("SIGINT",()=>{o(),i(),t.unsubscribeEvents(e).catch(()=>{}),t.close(),r(130)}),s}function X(n){let e=Z(n.ts);switch(n.type){case"ready":return`[${e}] ready ${n.provider} @ ${n.cwd}`;case"prompt-received":return`[${e}] prompt "${p(n.text,120)}"`;case"turn-started":return`[${e}] turn-started ${n.turnId??""}`;case"turn-message":return`[${e}] turn-message ${n.delta.replace(/\s+$/,"")}`;case"turn-reasoning":return`[${e}] turn-reasoning ${p(n.delta,200)}`;case"tool-call":return`[${e}] tool-call ${n.name}`;case"file-edited":return`[${e}] file-edited ${n.kind.padEnd(6)} ${n.path}`;case"turn-completed":return`[${e}] turn-completed ${n.durationMs}ms files=${n.filesTouched.length}`;case"approval-needed":return`[${e}] approval ${n.kind}`;case"error":return`[${e}] error ${n.message}`;case"exited":return`[${e}] exited code=${n.code}`;case"file-diff-delta":return`[${e}] file-diff-delta ${n.path}`;case"turn-plan":return`[${e}] turn-plan steps=${n.steps.length}`;default:return`[${e}] ${n.type}`}}async function z(n){let e=n[0];if(!e)return process.stderr.write(`usage: rnx agent transcript <sessionId>
|
|
40
|
-
`),2;let t=g(e);return w.existsSync(t)?(process.stdout.write(w.readFileSync(t,"utf8")),0):(process.stderr.write(`transcript not found: ${t}
|
|
41
|
-
`),1)}async function Q(n){let e=n[0];return e?(await v(t=>t.endSession(e)),process.stdout.write(`\u2713 ended session ${e}
|
|
42
|
-
`),0):(process.stderr.write(`usage: rnx agent end <sessionId>
|
|
43
|
-
`),2)}async function Y(){let n=E();return process.stdout.write(`userData: ${n}
|
|
44
|
-
state: ${d.join(n,"attached-projects.json")}
|
|
45
|
-
sessions: ${d.join(n,"sessions")}
|
|
46
|
-
transcripts: ${d.join(n,"transcripts")}
|
|
47
|
-
locks: ${d.join(n,"locks")}
|
|
48
|
-
`),0}function p(n,e){return n.length<=e?n:n.slice(0,e-1)+"\u2026"}function N(n){return n.length>14?`${n.slice(0,14)}\u2026`:n}function Z(n){return new Date(n).toISOString().replace("T"," ").slice(0,19)}var fe={sessionDir:I,promptFifoPath:k,eventsFifoPath:D,transcriptPath:g,parseAgentEventLine:b};export{fe as __internals,ge as runAgentCommand};
|