rnxsim 0.1.487 → 0.1.489
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/cli/bridge-flow-runner.ts +12 -17
- package/cli/commands/flow.ts +4 -0
- package/cli/outbound-endpoints.ts +2 -2
- package/cli/ws-bridge.ts +1 -1
- package/detox/index.ts +108 -9
- package/detox/proof-frame.cjs +10 -0
- package/dist-lib/agent-daemon-client.cjs +2 -2
- 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 +2 -2
- 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/capture-contract.cjs +1 -1
- package/dist-lib/capture-contract.mjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/cloud-contract.cjs +1 -1
- package/dist-lib/cloud-contract.mjs +1 -1
- package/dist-lib/cloud.cjs +1 -1
- package/dist-lib/cloud.mjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +101 -10
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +1 -1
- 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 +2 -2
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro-fingerprint-registry.cjs +1 -1
- package/dist-lib/metro-fingerprint-registry.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 +1 -1
- package/dist-lib/profiles.cjs +1 -1
- 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 +1 -1
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +13 -18
- package/dist-lib/vite.cjs +1 -1
- package/package.json +1 -1
- package/src/agent-daemon-client.ts +1 -1
- package/src/bridge-constants.ts +6 -1
|
@@ -2,10 +2,7 @@ import * as fs from 'fs'
|
|
|
2
2
|
import * as path from 'path'
|
|
3
3
|
import { devices, type DeviceModel } from 'sootsim-engine/settings'
|
|
4
4
|
import yaml from 'yaml'
|
|
5
|
-
import {
|
|
6
|
-
REQUIRED_IDENTICAL_PROOF_FRAMES,
|
|
7
|
-
framesIdentical,
|
|
8
|
-
} from '../detox/proof-frame.cjs'
|
|
5
|
+
import { REQUIRED_IDENTICAL_FLOW_FRAMES, framesIdentical } from '../detox/proof-frame.cjs'
|
|
9
6
|
import { flowTimeoutScale } from '../src/flow-timeout-scale'
|
|
10
7
|
import { composeFramedScreenshot } from '../src/screenshots/frame-compose'
|
|
11
8
|
import { inspectWaitReady, waitReadyReason } from './commands/inspect/core'
|
|
@@ -1434,20 +1431,18 @@ export class SootSimBridgeFlowRunner {
|
|
|
1434
1431
|
dataUrl.replace(/^data:image\/png;base64,/, ''),
|
|
1435
1432
|
'base64',
|
|
1436
1433
|
)
|
|
1437
|
-
|
|
1438
|
-
identicalFrames++
|
|
1439
|
-
if (identicalFrames >= REQUIRED_IDENTICAL_PROOF_FRAMES) {
|
|
1440
|
-
rawBuffer = current
|
|
1441
|
-
break
|
|
1442
|
-
}
|
|
1443
|
-
} else {
|
|
1444
|
-
identicalFrames = 1
|
|
1445
|
-
}
|
|
1434
|
+
identicalFrames = framesIdentical(previousBuffer, current) ? identicalFrames + 1 : 1
|
|
1446
1435
|
previousBuffer = current
|
|
1436
|
+
// checked after the capture, so the constant is a capture count: at 1
|
|
1437
|
+
// the first settled frame is the screenshot and nothing re-captures.
|
|
1438
|
+
if (identicalFrames >= REQUIRED_IDENTICAL_FLOW_FRAMES) {
|
|
1439
|
+
rawBuffer = current
|
|
1440
|
+
break
|
|
1441
|
+
}
|
|
1447
1442
|
}
|
|
1448
1443
|
if (!rawBuffer) {
|
|
1449
1444
|
throw new Error(
|
|
1450
|
-
`screenshot did not reach ${
|
|
1445
|
+
`screenshot did not reach ${REQUIRED_IDENTICAL_FLOW_FRAMES} identical idle frames`,
|
|
1451
1446
|
)
|
|
1452
1447
|
}
|
|
1453
1448
|
if (spec.withFrame) {
|
|
@@ -2026,6 +2021,9 @@ export class SootSimBridgeFlowRunner {
|
|
|
2026
2021
|
await this.startProfile()
|
|
2027
2022
|
}
|
|
2028
2023
|
if (this.recordingEnabled) {
|
|
2024
|
+
// a flow that starts with launchApp prepares recording before the step.
|
|
2025
|
+
// begin its pixels only after launch has mounted and settled, leaving the
|
|
2026
|
+
// loading prelude outside the playable video while its trace stays visible.
|
|
2029
2027
|
await this.waitForVisualSettle()
|
|
2030
2028
|
await this.ensureRecordingStarted()
|
|
2031
2029
|
}
|
|
@@ -2088,9 +2086,6 @@ export class SootSimBridgeFlowRunner {
|
|
|
2088
2086
|
if (state?.state !== 'home' || state.activeApp != null) return false
|
|
2089
2087
|
|
|
2090
2088
|
const appId = this.resolveShellLaunchAppId(opts, state)
|
|
2091
|
-
if (this.recordingEnabled) {
|
|
2092
|
-
await this.ensureRecordingStarted()
|
|
2093
|
-
}
|
|
2094
2089
|
await callShellCommandWhenReady(this.bridge, 'launchApp', 1000, appId)
|
|
2095
2090
|
await this.waitForShellAppLaunched(appId, 1000)
|
|
2096
2091
|
return true
|
package/cli/commands/flow.ts
CHANGED
|
@@ -572,6 +572,10 @@ flow extension:
|
|
|
572
572
|
commandTimeoutMs: resolvedBridgeArgs.commandTimeoutMs,
|
|
573
573
|
simId: pinnedSimId,
|
|
574
574
|
simIdSource: pinnedSimIdSource,
|
|
575
|
+
// the shell prints `lockedBy` over the device while the flow drives it.
|
|
576
|
+
// without a label that falls back to the cli identity key, which is an
|
|
577
|
+
// internal `ENV_VAR:value` string rather than something a viewer reads.
|
|
578
|
+
cliLabel: 'maestro test',
|
|
575
579
|
})
|
|
576
580
|
let driver: SootSimBridgeFlowRunner
|
|
577
581
|
const applySimSettings = async () => {
|
|
@@ -485,7 +485,7 @@ export const DECLARED_OUTBOUND_CALLS: Record<string, OutboundCallDeclaration> =
|
|
|
485
485
|
count: 1,
|
|
486
486
|
},
|
|
487
487
|
// the inventory records the call expression, not the URL, so this entry can
|
|
488
|
-
// no longer show its own destination. bridgeWsUrl() is
|
|
488
|
+
// no longer show its own destination. bridgeWsUrl() is loopback-only today;
|
|
489
489
|
// when a cloud box makes it return a remote wss:// endpoint, that egress
|
|
490
490
|
// would land under this same local_development entry and go unnoticed. split
|
|
491
491
|
// the declaration then, rather than letting one line cover both.
|
|
@@ -497,7 +497,7 @@ export const DECLARED_OUTBOUND_CALLS: Record<string, OutboundCallDeclaration> =
|
|
|
497
497
|
category: 'local_development',
|
|
498
498
|
count: 1,
|
|
499
499
|
},
|
|
500
|
-
'packages/sootsim/src/agent-daemon-client.ts :: websocket :: `ws://
|
|
500
|
+
'packages/sootsim/src/agent-daemon-client.ts :: websocket :: `ws://127.0.0.1:${this.port}`':
|
|
501
501
|
{ category: 'local_development', count: 1 },
|
|
502
502
|
"packages/sootsim/src/auth/shared-session.ts :: fetch :: `${origin.replace(/\\/$/, '')}/api/auth/me`":
|
|
503
503
|
{ category: 'contrast_user_action', count: 1 },
|
package/cli/ws-bridge.ts
CHANGED
|
@@ -75,7 +75,7 @@ export function resolvePlacement(): RnxPlacement {
|
|
|
75
75
|
* this function. a cloud endpoint added here must get its own declaration in
|
|
76
76
|
* `outbound-endpoints.ts` instead of inheriting the local_development one. */
|
|
77
77
|
export function bridgeWsUrl(wsPort: number): string {
|
|
78
|
-
return `ws://
|
|
78
|
+
return `ws://127.0.0.1:${wsPort}`
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
// resolved once per CLI process so a multi-step command keeps one world for
|
package/detox/index.ts
CHANGED
|
@@ -801,6 +801,102 @@ async function dispatchStatusBarOverride(config: StatusBarConfig) {
|
|
|
801
801
|
await page.waitForTimeout(50)
|
|
802
802
|
}
|
|
803
803
|
|
|
804
|
+
const MAX_SETTLED_SPEED_PT_PER_SEC = 2.0
|
|
805
|
+
|
|
806
|
+
async function waitForFrameClock(page: Page, minMs = 25): Promise<void> {
|
|
807
|
+
const start = performance.now()
|
|
808
|
+
await page.evaluate(
|
|
809
|
+
() =>
|
|
810
|
+
new Promise<void>((resolve) => {
|
|
811
|
+
const timeoutId = setTimeout(() => resolve(), 50)
|
|
812
|
+
requestAnimationFrame(() => {
|
|
813
|
+
clearTimeout(timeoutId)
|
|
814
|
+
resolve()
|
|
815
|
+
})
|
|
816
|
+
}),
|
|
817
|
+
)
|
|
818
|
+
const elapsed = performance.now() - start
|
|
819
|
+
if (elapsed < minMs) {
|
|
820
|
+
await page.waitForTimeout(minMs - elapsed)
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
async function findStableNodeByMatcher(
|
|
825
|
+
matcher: Matcher,
|
|
826
|
+
action = 'tap',
|
|
827
|
+
maxWaitMs = 1500,
|
|
828
|
+
): Promise<any> {
|
|
829
|
+
const page = getPage()
|
|
830
|
+
const start = performance.now()
|
|
831
|
+
let lastPos: { x: number; y: number } | null = null
|
|
832
|
+
let lastTime: number | null = null
|
|
833
|
+
let lastRate: { vx: number; vy: number; speed: number } | null = null
|
|
834
|
+
let sampleCount = 0
|
|
835
|
+
let stablePolls = 0
|
|
836
|
+
const requiredStable = 2
|
|
837
|
+
let hadNumericLayout = false
|
|
838
|
+
let disappearedMidWait = false
|
|
839
|
+
|
|
840
|
+
while (performance.now() - start < maxWaitMs) {
|
|
841
|
+
const node = await findNodeByMatcher(matcher)
|
|
842
|
+
if (!node) {
|
|
843
|
+
if (hadNumericLayout) {
|
|
844
|
+
disappearedMidWait = true
|
|
845
|
+
} else {
|
|
846
|
+
return null
|
|
847
|
+
}
|
|
848
|
+
} else {
|
|
849
|
+
disappearedMidWait = false
|
|
850
|
+
const pos = node.absolutePosition ?? node.layout
|
|
851
|
+
if (pos && typeof pos.x === 'number' && typeof pos.y === 'number') {
|
|
852
|
+
hadNumericLayout = true
|
|
853
|
+
sampleCount++
|
|
854
|
+
const now = performance.now()
|
|
855
|
+
if (lastPos && lastTime !== null) {
|
|
856
|
+
const dtSec = (now - lastTime) / 1000
|
|
857
|
+
if (dtSec > 0.005) {
|
|
858
|
+
const vx = Math.abs(pos.x - lastPos.x) / dtSec
|
|
859
|
+
const vy = Math.abs(pos.y - lastPos.y) / dtSec
|
|
860
|
+
const speed = Math.sqrt(vx * vx + vy * vy)
|
|
861
|
+
lastRate = { vx, vy, speed }
|
|
862
|
+
if (speed < MAX_SETTLED_SPEED_PT_PER_SEC) {
|
|
863
|
+
stablePolls++
|
|
864
|
+
if (stablePolls >= requiredStable) {
|
|
865
|
+
return node
|
|
866
|
+
}
|
|
867
|
+
} else {
|
|
868
|
+
stablePolls = 0
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
lastPos = { x: pos.x, y: pos.y }
|
|
873
|
+
lastTime = now
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
await waitForFrameClock(page, 25)
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
const elapsed = Math.round(performance.now() - start)
|
|
880
|
+
if (disappearedMidWait) {
|
|
881
|
+
throw new Error(
|
|
882
|
+
`element disappeared while waiting to come to rest for ${action}: ${JSON.stringify(matcher)} after ${elapsed}ms`,
|
|
883
|
+
)
|
|
884
|
+
}
|
|
885
|
+
if (!hadNumericLayout) {
|
|
886
|
+
throw new Error(
|
|
887
|
+
`element layout is not available for ${action}: ${JSON.stringify(matcher)} after ${elapsed}ms`,
|
|
888
|
+
)
|
|
889
|
+
}
|
|
890
|
+
if (sampleCount < 2 || lastRate === null) {
|
|
891
|
+
throw new Error(
|
|
892
|
+
`element did not come to rest for ${action}: ${JSON.stringify(matcher)}; only one sample obtained after ${elapsed}ms`,
|
|
893
|
+
)
|
|
894
|
+
}
|
|
895
|
+
throw new Error(
|
|
896
|
+
`element did not come to rest for ${action}: ${JSON.stringify(matcher)}; still moving ${lastRate.vx.toFixed(1)} points/sec x / ${lastRate.vy.toFixed(1)} points/sec y after ${elapsed}ms`,
|
|
897
|
+
)
|
|
898
|
+
}
|
|
899
|
+
|
|
804
900
|
function createSootSimElement(matcher: Matcher): SootSimElement {
|
|
805
901
|
const el: SootSimElement = {
|
|
806
902
|
_matcher: matcher,
|
|
@@ -808,7 +904,7 @@ function createSootSimElement(matcher: Matcher): SootSimElement {
|
|
|
808
904
|
async tap(point) {
|
|
809
905
|
const page = getPage()
|
|
810
906
|
await waitForSootsimWorkletsIdle(page, 3000)
|
|
811
|
-
const node = await
|
|
907
|
+
const node = await findStableNodeByMatcher(matcher, 'tap')
|
|
812
908
|
if (!node) throw new Error(`element not found for tap: ${JSON.stringify(matcher)}`)
|
|
813
909
|
if (!isNodeVisible(node)) {
|
|
814
910
|
throw new Error(
|
|
@@ -837,7 +933,7 @@ function createSootSimElement(matcher: Matcher): SootSimElement {
|
|
|
837
933
|
// center with a small inter-tap pause that stays inside RNGH's
|
|
838
934
|
// default maxDelay window of 200ms.
|
|
839
935
|
const page = getPage()
|
|
840
|
-
const node = await
|
|
936
|
+
const node = await findStableNodeByMatcher(matcher, 'multiTap')
|
|
841
937
|
if (!node)
|
|
842
938
|
throw new Error(`element not found for multiTap: ${JSON.stringify(matcher)}`)
|
|
843
939
|
if (!isNodeVisible(node)) {
|
|
@@ -867,7 +963,7 @@ function createSootSimElement(matcher: Matcher): SootSimElement {
|
|
|
867
963
|
durationArg = 1000,
|
|
868
964
|
) {
|
|
869
965
|
const page = getPage()
|
|
870
|
-
const node = await
|
|
966
|
+
const node = await findStableNodeByMatcher(matcher, 'longPress')
|
|
871
967
|
if (!node)
|
|
872
968
|
throw new Error(`element not found for longPress: ${JSON.stringify(matcher)}`)
|
|
873
969
|
if (!isNodeVisible(node)) {
|
|
@@ -911,12 +1007,15 @@ function createSootSimElement(matcher: Matcher): SootSimElement {
|
|
|
911
1007
|
) {
|
|
912
1008
|
const page = getPage()
|
|
913
1009
|
// resolve source element
|
|
914
|
-
const srcNode = await
|
|
1010
|
+
const srcNode = await findStableNodeByMatcher(matcher, 'longPressAndDrag')
|
|
915
1011
|
if (!srcNode)
|
|
916
1012
|
throw new Error(`source element not found: ${JSON.stringify(matcher)}`)
|
|
917
1013
|
|
|
918
1014
|
// resolve target element
|
|
919
|
-
const tgtNode = await
|
|
1015
|
+
const tgtNode = await findStableNodeByMatcher(
|
|
1016
|
+
targetElement._matcher,
|
|
1017
|
+
'longPressAndDrag',
|
|
1018
|
+
)
|
|
920
1019
|
if (!tgtNode)
|
|
921
1020
|
throw new Error(
|
|
922
1021
|
`target element not found: ${JSON.stringify(targetElement._matcher)}`,
|
|
@@ -1098,7 +1197,7 @@ function createSootSimElement(matcher: Matcher): SootSimElement {
|
|
|
1098
1197
|
normalizedStartingPointX = 0.5,
|
|
1099
1198
|
normalizedStartingPointY = 0.5,
|
|
1100
1199
|
) {
|
|
1101
|
-
const node = await
|
|
1200
|
+
const node = await findStableNodeByMatcher(matcher, 'swipe')
|
|
1102
1201
|
if (!node)
|
|
1103
1202
|
throw new Error(`element not found for swipe: ${JSON.stringify(matcher)}`)
|
|
1104
1203
|
|
|
@@ -1172,7 +1271,7 @@ function createSootSimElement(matcher: Matcher): SootSimElement {
|
|
|
1172
1271
|
throw new Error(`picker value must be a string, got ${typeof value}`)
|
|
1173
1272
|
}
|
|
1174
1273
|
|
|
1175
|
-
const picker = await
|
|
1274
|
+
const picker = await findStableNodeByMatcher(matcher, 'setColumnToValue')
|
|
1176
1275
|
if (!picker) {
|
|
1177
1276
|
throw new Error(
|
|
1178
1277
|
`element not found for setColumnToValue: ${JSON.stringify(matcher)}`,
|
|
@@ -1249,7 +1348,7 @@ function createSootSimElement(matcher: Matcher): SootSimElement {
|
|
|
1249
1348
|
// velocity tracking sees a realistic delta. angle (radians) tilts the
|
|
1250
1349
|
// pinch axis off horizontal — matches Detox's third arg.
|
|
1251
1350
|
const page = getPage()
|
|
1252
|
-
const node = await
|
|
1351
|
+
const node = await findStableNodeByMatcher(matcher, 'pinch')
|
|
1253
1352
|
if (!node)
|
|
1254
1353
|
throw new Error(`element not found for pinch: ${JSON.stringify(matcher)}`)
|
|
1255
1354
|
if (!node.nativePinchEnabled) {
|
|
@@ -1284,7 +1383,7 @@ function createSootSimElement(matcher: Matcher): SootSimElement {
|
|
|
1284
1383
|
// sign (its 'rotation' delta is positive for a counter-clockwise
|
|
1285
1384
|
// motion of the rear finger relative to the front finger).
|
|
1286
1385
|
const page = getPage()
|
|
1287
|
-
const node = await
|
|
1386
|
+
const node = await findStableNodeByMatcher(matcher, 'rotate')
|
|
1288
1387
|
if (!node)
|
|
1289
1388
|
throw new Error(`element not found for rotate: ${JSON.stringify(matcher)}`)
|
|
1290
1389
|
await waitForSootsimGestureHandler(page, node.nodeId, 'RotationGestureHandler')
|
package/detox/proof-frame.cjs
CHANGED
|
@@ -7,8 +7,17 @@ const PROOF_CONTENT_DEFINITION = Object.freeze({
|
|
|
7
7
|
minimumContentPercent: 0.005,
|
|
8
8
|
})
|
|
9
9
|
|
|
10
|
+
// conformance compares these captures against native ios baselines, so a frame
|
|
11
|
+
// caught mid-animation reads as a real pixel diff. three consecutive identical
|
|
12
|
+
// frames is the evidence that the screen actually stopped moving.
|
|
10
13
|
const REQUIRED_IDENTICAL_PROOF_FRAMES = 3
|
|
11
14
|
|
|
15
|
+
// a flow's `takeScreenshot` is a developer artifact, not pixel evidence. one
|
|
16
|
+
// settled capture is what it wants: re-capturing flashes the screen on every
|
|
17
|
+
// attempt, and a screen with a blinking caret never produces two identical
|
|
18
|
+
// frames at all, so the step fails on a page that is perfectly fine.
|
|
19
|
+
const REQUIRED_IDENTICAL_FLOW_FRAMES = 1
|
|
20
|
+
|
|
12
21
|
function framesIdentical(a, b) {
|
|
13
22
|
if (!a || !b || a.length !== b.length) return false
|
|
14
23
|
return a.equals(b)
|
|
@@ -98,6 +107,7 @@ function settleDecision(previousPixels, currentFrame) {
|
|
|
98
107
|
module.exports = {
|
|
99
108
|
PROOF_CONTENT_DEFINITION,
|
|
100
109
|
REQUIRED_IDENTICAL_PROOF_FRAMES,
|
|
110
|
+
REQUIRED_IDENTICAL_FLOW_FRAMES,
|
|
101
111
|
framesIdentical,
|
|
102
112
|
measureProofFrameContent,
|
|
103
113
|
settleDecision,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -241,7 +241,7 @@ var AgentDaemonClient = class {
|
|
|
241
241
|
constructor(opts = {}) {
|
|
242
242
|
this.port = opts.port ?? DEFAULT_SOOTSIM_BRIDGE_PORT;
|
|
243
243
|
this.commandTimeoutMs = opts.commandTimeoutMs ?? 15e3;
|
|
244
|
-
this.ws = new import_ws.WebSocket(`ws://
|
|
244
|
+
this.ws = new import_ws.WebSocket(`ws://127.0.0.1:${this.port}`);
|
|
245
245
|
this.ready = new Promise((resolve, reject) => {
|
|
246
246
|
const onOpen = () => {
|
|
247
247
|
this.ws.off("error", onError);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
package/dist-lib/beta.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
package/dist-lib/beta.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -136,7 +136,7 @@ function resolveSootsimWebSocketProxyUrl(input) {
|
|
|
136
136
|
}
|
|
137
137
|
function resolveSootsimBridgeWebSocketUrl(input) {
|
|
138
138
|
return resolveSootsimWebSocketProxyUrl({
|
|
139
|
-
targetUrl: `ws://
|
|
139
|
+
targetUrl: `ws://127.0.0.1:${input.bridgePort}`,
|
|
140
140
|
href: input.href
|
|
141
141
|
});
|
|
142
142
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
package/dist-lib/cloud.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
package/dist-lib/cloud.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
package/dist-lib/config.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
package/dist-lib/detox/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -146,6 +146,7 @@ var require_proof_frame = __commonJS({
|
|
|
146
146
|
minimumContentPercent: 5e-3
|
|
147
147
|
});
|
|
148
148
|
var REQUIRED_IDENTICAL_PROOF_FRAMES2 = 3;
|
|
149
|
+
var REQUIRED_IDENTICAL_FLOW_FRAMES = 1;
|
|
149
150
|
function framesIdentical2(a, b) {
|
|
150
151
|
if (!a || !b || a.length !== b.length) return false;
|
|
151
152
|
return a.equals(b);
|
|
@@ -215,6 +216,7 @@ var require_proof_frame = __commonJS({
|
|
|
215
216
|
module2.exports = {
|
|
216
217
|
PROOF_CONTENT_DEFINITION,
|
|
217
218
|
REQUIRED_IDENTICAL_PROOF_FRAMES: REQUIRED_IDENTICAL_PROOF_FRAMES2,
|
|
219
|
+
REQUIRED_IDENTICAL_FLOW_FRAMES,
|
|
218
220
|
framesIdentical: framesIdentical2,
|
|
219
221
|
measureProofFrameContent,
|
|
220
222
|
settleDecision
|
|
@@ -2448,13 +2450,99 @@ async function dispatchStatusBarOverride(config) {
|
|
|
2448
2450
|
);
|
|
2449
2451
|
await page.waitForTimeout(50);
|
|
2450
2452
|
}
|
|
2453
|
+
var MAX_SETTLED_SPEED_PT_PER_SEC = 2;
|
|
2454
|
+
async function waitForFrameClock(page, minMs = 25) {
|
|
2455
|
+
const start = performance.now();
|
|
2456
|
+
await page.evaluate(
|
|
2457
|
+
() => new Promise((resolve) => {
|
|
2458
|
+
const timeoutId = setTimeout(() => resolve(), 50);
|
|
2459
|
+
requestAnimationFrame(() => {
|
|
2460
|
+
clearTimeout(timeoutId);
|
|
2461
|
+
resolve();
|
|
2462
|
+
});
|
|
2463
|
+
})
|
|
2464
|
+
);
|
|
2465
|
+
const elapsed = performance.now() - start;
|
|
2466
|
+
if (elapsed < minMs) {
|
|
2467
|
+
await page.waitForTimeout(minMs - elapsed);
|
|
2468
|
+
}
|
|
2469
|
+
}
|
|
2470
|
+
async function findStableNodeByMatcher(matcher, action = "tap", maxWaitMs = 1500) {
|
|
2471
|
+
const page = getPage();
|
|
2472
|
+
const start = performance.now();
|
|
2473
|
+
let lastPos = null;
|
|
2474
|
+
let lastTime = null;
|
|
2475
|
+
let lastRate = null;
|
|
2476
|
+
let sampleCount = 0;
|
|
2477
|
+
let stablePolls = 0;
|
|
2478
|
+
const requiredStable = 2;
|
|
2479
|
+
let hadNumericLayout = false;
|
|
2480
|
+
let disappearedMidWait = false;
|
|
2481
|
+
while (performance.now() - start < maxWaitMs) {
|
|
2482
|
+
const node = await findNodeByMatcher(matcher);
|
|
2483
|
+
if (!node) {
|
|
2484
|
+
if (hadNumericLayout) {
|
|
2485
|
+
disappearedMidWait = true;
|
|
2486
|
+
} else {
|
|
2487
|
+
return null;
|
|
2488
|
+
}
|
|
2489
|
+
} else {
|
|
2490
|
+
disappearedMidWait = false;
|
|
2491
|
+
const pos = node.absolutePosition ?? node.layout;
|
|
2492
|
+
if (pos && typeof pos.x === "number" && typeof pos.y === "number") {
|
|
2493
|
+
hadNumericLayout = true;
|
|
2494
|
+
sampleCount++;
|
|
2495
|
+
const now = performance.now();
|
|
2496
|
+
if (lastPos && lastTime !== null) {
|
|
2497
|
+
const dtSec = (now - lastTime) / 1e3;
|
|
2498
|
+
if (dtSec > 5e-3) {
|
|
2499
|
+
const vx = Math.abs(pos.x - lastPos.x) / dtSec;
|
|
2500
|
+
const vy = Math.abs(pos.y - lastPos.y) / dtSec;
|
|
2501
|
+
const speed = Math.sqrt(vx * vx + vy * vy);
|
|
2502
|
+
lastRate = { vx, vy, speed };
|
|
2503
|
+
if (speed < MAX_SETTLED_SPEED_PT_PER_SEC) {
|
|
2504
|
+
stablePolls++;
|
|
2505
|
+
if (stablePolls >= requiredStable) {
|
|
2506
|
+
return node;
|
|
2507
|
+
}
|
|
2508
|
+
} else {
|
|
2509
|
+
stablePolls = 0;
|
|
2510
|
+
}
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2513
|
+
lastPos = { x: pos.x, y: pos.y };
|
|
2514
|
+
lastTime = now;
|
|
2515
|
+
}
|
|
2516
|
+
}
|
|
2517
|
+
await waitForFrameClock(page, 25);
|
|
2518
|
+
}
|
|
2519
|
+
const elapsed = Math.round(performance.now() - start);
|
|
2520
|
+
if (disappearedMidWait) {
|
|
2521
|
+
throw new Error(
|
|
2522
|
+
`element disappeared while waiting to come to rest for ${action}: ${JSON.stringify(matcher)} after ${elapsed}ms`
|
|
2523
|
+
);
|
|
2524
|
+
}
|
|
2525
|
+
if (!hadNumericLayout) {
|
|
2526
|
+
throw new Error(
|
|
2527
|
+
`element layout is not available for ${action}: ${JSON.stringify(matcher)} after ${elapsed}ms`
|
|
2528
|
+
);
|
|
2529
|
+
}
|
|
2530
|
+
if (sampleCount < 2 || lastRate === null) {
|
|
2531
|
+
throw new Error(
|
|
2532
|
+
`element did not come to rest for ${action}: ${JSON.stringify(matcher)}; only one sample obtained after ${elapsed}ms`
|
|
2533
|
+
);
|
|
2534
|
+
}
|
|
2535
|
+
throw new Error(
|
|
2536
|
+
`element did not come to rest for ${action}: ${JSON.stringify(matcher)}; still moving ${lastRate.vx.toFixed(1)} points/sec x / ${lastRate.vy.toFixed(1)} points/sec y after ${elapsed}ms`
|
|
2537
|
+
);
|
|
2538
|
+
}
|
|
2451
2539
|
function createSootSimElement(matcher) {
|
|
2452
2540
|
const el = {
|
|
2453
2541
|
_matcher: matcher,
|
|
2454
2542
|
async tap(point) {
|
|
2455
2543
|
const page = getPage();
|
|
2456
2544
|
await waitForSootsimWorkletsIdle(page, 3e3);
|
|
2457
|
-
const node = await
|
|
2545
|
+
const node = await findStableNodeByMatcher(matcher, "tap");
|
|
2458
2546
|
if (!node) throw new Error(`element not found for tap: ${JSON.stringify(matcher)}`);
|
|
2459
2547
|
if (!isNodeVisible(node)) {
|
|
2460
2548
|
throw new Error(
|
|
@@ -2471,7 +2559,7 @@ function createSootSimElement(matcher) {
|
|
|
2471
2559
|
},
|
|
2472
2560
|
async multiTap(times) {
|
|
2473
2561
|
const page = getPage();
|
|
2474
|
-
const node = await
|
|
2562
|
+
const node = await findStableNodeByMatcher(matcher, "multiTap");
|
|
2475
2563
|
if (!node)
|
|
2476
2564
|
throw new Error(`element not found for multiTap: ${JSON.stringify(matcher)}`);
|
|
2477
2565
|
if (!isNodeVisible(node)) {
|
|
@@ -2496,7 +2584,7 @@ function createSootSimElement(matcher) {
|
|
|
2496
2584
|
// where the point is relative to the element's origin
|
|
2497
2585
|
async longPress(pointOrDuration, durationArg = 1e3) {
|
|
2498
2586
|
const page = getPage();
|
|
2499
|
-
const node = await
|
|
2587
|
+
const node = await findStableNodeByMatcher(matcher, "longPress");
|
|
2500
2588
|
if (!node)
|
|
2501
2589
|
throw new Error(`element not found for longPress: ${JSON.stringify(matcher)}`);
|
|
2502
2590
|
if (!isNodeVisible(node)) {
|
|
@@ -2526,10 +2614,13 @@ function createSootSimElement(matcher) {
|
|
|
2526
2614
|
},
|
|
2527
2615
|
async longPressAndDrag(duration, normalizedStartX, normalizedStartY, targetElement, normalizedEndX, normalizedEndY, speed = "fast", holdDuration = 0) {
|
|
2528
2616
|
const page = getPage();
|
|
2529
|
-
const srcNode = await
|
|
2617
|
+
const srcNode = await findStableNodeByMatcher(matcher, "longPressAndDrag");
|
|
2530
2618
|
if (!srcNode)
|
|
2531
2619
|
throw new Error(`source element not found: ${JSON.stringify(matcher)}`);
|
|
2532
|
-
const tgtNode = await
|
|
2620
|
+
const tgtNode = await findStableNodeByMatcher(
|
|
2621
|
+
targetElement._matcher,
|
|
2622
|
+
"longPressAndDrag"
|
|
2623
|
+
);
|
|
2533
2624
|
if (!tgtNode)
|
|
2534
2625
|
throw new Error(
|
|
2535
2626
|
`target element not found: ${JSON.stringify(targetElement._matcher)}`
|
|
@@ -2651,7 +2742,7 @@ function createSootSimElement(matcher) {
|
|
|
2651
2742
|
}
|
|
2652
2743
|
},
|
|
2653
2744
|
async swipe(direction, speed = "fast", percentage = 0.75, normalizedStartingPointX = 0.5, normalizedStartingPointY = 0.5) {
|
|
2654
|
-
const node = await
|
|
2745
|
+
const node = await findStableNodeByMatcher(matcher, "swipe");
|
|
2655
2746
|
if (!node)
|
|
2656
2747
|
throw new Error(`element not found for swipe: ${JSON.stringify(matcher)}`);
|
|
2657
2748
|
const page = getPage();
|
|
@@ -2704,7 +2795,7 @@ function createSootSimElement(matcher) {
|
|
|
2704
2795
|
if (typeof value !== "string") {
|
|
2705
2796
|
throw new Error(`picker value must be a string, got ${typeof value}`);
|
|
2706
2797
|
}
|
|
2707
|
-
const picker = await
|
|
2798
|
+
const picker = await findStableNodeByMatcher(matcher, "setColumnToValue");
|
|
2708
2799
|
if (!picker) {
|
|
2709
2800
|
throw new Error(
|
|
2710
2801
|
`element not found for setColumnToValue: ${JSON.stringify(matcher)}`
|
|
@@ -2760,7 +2851,7 @@ function createSootSimElement(matcher) {
|
|
|
2760
2851
|
},
|
|
2761
2852
|
async pinch(scale, speed = "fast", angle = 0) {
|
|
2762
2853
|
const page = getPage();
|
|
2763
|
-
const node = await
|
|
2854
|
+
const node = await findStableNodeByMatcher(matcher, "pinch");
|
|
2764
2855
|
if (!node)
|
|
2765
2856
|
throw new Error(`element not found for pinch: ${JSON.stringify(matcher)}`);
|
|
2766
2857
|
if (!node.nativePinchEnabled) {
|
|
@@ -2789,7 +2880,7 @@ function createSootSimElement(matcher) {
|
|
|
2789
2880
|
},
|
|
2790
2881
|
async rotate(radians, speed = "fast") {
|
|
2791
2882
|
const page = getPage();
|
|
2792
|
-
const node = await
|
|
2883
|
+
const node = await findStableNodeByMatcher(matcher, "rotate");
|
|
2793
2884
|
if (!node)
|
|
2794
2885
|
throw new Error(`element not found for rotate: ${JSON.stringify(matcher)}`);
|
|
2795
2886
|
await waitForSootsimGestureHandler(page, node.nodeId, "RotationGestureHandler");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
package/dist-lib/home-paths.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
|
|
3
3
|
// src/host/fetch-proxy-overrides.ts
|
|
4
4
|
var FETCH_PROXY_BROWSER_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
package/dist-lib/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -904,7 +904,7 @@ var DEFAULT_SOOTSIM_SHELL_URL = "http://localhost:5173/";
|
|
|
904
904
|
|
|
905
905
|
// cli/ws-bridge.ts
|
|
906
906
|
function bridgeWsUrl(wsPort) {
|
|
907
|
-
return `ws://
|
|
907
|
+
return `ws://127.0.0.1:${wsPort}`;
|
|
908
908
|
}
|
|
909
909
|
var resolvedWorld = null;
|
|
910
910
|
function liveDevBridgeLockfiles() {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
package/dist-lib/menu.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
package/dist-lib/menu.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
package/dist-lib/metro.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
package/dist-lib/profiles.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
package/dist-lib/render-mode.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
package/dist-lib/sdk.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
package/dist-lib/sdk.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
package/dist-lib/skills.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -19233,7 +19233,7 @@ function resolveSootsimWebSocketProxyUrl(input) {
|
|
|
19233
19233
|
}
|
|
19234
19234
|
function resolveSootsimBridgeWebSocketUrl(input) {
|
|
19235
19235
|
return resolveSootsimWebSocketProxyUrl({
|
|
19236
|
-
targetUrl: `ws://
|
|
19236
|
+
targetUrl: `ws://127.0.0.1:${input.bridgePort}`,
|
|
19237
19237
|
href: input.href
|
|
19238
19238
|
});
|
|
19239
19239
|
}
|
|
@@ -30949,7 +30949,7 @@ function resolvePlacement() {
|
|
|
30949
30949
|
return process.env[RNX_PLACEMENT_ENV] === "local-box" ? "local-box" : "host";
|
|
30950
30950
|
}
|
|
30951
30951
|
function bridgeWsUrl(wsPort) {
|
|
30952
|
-
return `ws://
|
|
30952
|
+
return `ws://127.0.0.1:${wsPort}`;
|
|
30953
30953
|
}
|
|
30954
30954
|
function liveDevBridgeLockfiles() {
|
|
30955
30955
|
return readDevBridgeLockfiles().filter((lockfile) => isDevBridgeLockfileFresh(lockfile));
|
|
@@ -35512,7 +35512,8 @@ var require_proof_frame = __commonJS({
|
|
|
35512
35512
|
contentBandInsetFraction: 0.08,
|
|
35513
35513
|
minimumContentPercent: 5e-3
|
|
35514
35514
|
});
|
|
35515
|
-
var
|
|
35515
|
+
var REQUIRED_IDENTICAL_PROOF_FRAMES = 3;
|
|
35516
|
+
var REQUIRED_IDENTICAL_FLOW_FRAMES2 = 1;
|
|
35516
35517
|
function framesIdentical2(a, b) {
|
|
35517
35518
|
if (!a || !b || a.length !== b.length) return false;
|
|
35518
35519
|
return a.equals(b);
|
|
@@ -35581,7 +35582,8 @@ var require_proof_frame = __commonJS({
|
|
|
35581
35582
|
}
|
|
35582
35583
|
module2.exports = {
|
|
35583
35584
|
PROOF_CONTENT_DEFINITION,
|
|
35584
|
-
REQUIRED_IDENTICAL_PROOF_FRAMES
|
|
35585
|
+
REQUIRED_IDENTICAL_PROOF_FRAMES,
|
|
35586
|
+
REQUIRED_IDENTICAL_FLOW_FRAMES: REQUIRED_IDENTICAL_FLOW_FRAMES2,
|
|
35585
35587
|
framesIdentical: framesIdentical2,
|
|
35586
35588
|
measureProofFrameContent,
|
|
35587
35589
|
settleDecision
|
|
@@ -37342,20 +37344,16 @@ var init_bridge_flow_runner = __esm({
|
|
|
37342
37344
|
dataUrl.replace(/^data:image\/png;base64,/, ""),
|
|
37343
37345
|
"base64"
|
|
37344
37346
|
);
|
|
37345
|
-
|
|
37346
|
-
identicalFrames++;
|
|
37347
|
-
if (identicalFrames >= import_proof_frame.REQUIRED_IDENTICAL_PROOF_FRAMES) {
|
|
37348
|
-
rawBuffer = current;
|
|
37349
|
-
break;
|
|
37350
|
-
}
|
|
37351
|
-
} else {
|
|
37352
|
-
identicalFrames = 1;
|
|
37353
|
-
}
|
|
37347
|
+
identicalFrames = (0, import_proof_frame.framesIdentical)(previousBuffer, current) ? identicalFrames + 1 : 1;
|
|
37354
37348
|
previousBuffer = current;
|
|
37349
|
+
if (identicalFrames >= import_proof_frame.REQUIRED_IDENTICAL_FLOW_FRAMES) {
|
|
37350
|
+
rawBuffer = current;
|
|
37351
|
+
break;
|
|
37352
|
+
}
|
|
37355
37353
|
}
|
|
37356
37354
|
if (!rawBuffer) {
|
|
37357
37355
|
throw new Error(
|
|
37358
|
-
`screenshot did not reach ${import_proof_frame.
|
|
37356
|
+
`screenshot did not reach ${import_proof_frame.REQUIRED_IDENTICAL_FLOW_FRAMES} identical idle frames`
|
|
37359
37357
|
);
|
|
37360
37358
|
}
|
|
37361
37359
|
if (spec.withFrame) {
|
|
@@ -37867,9 +37865,6 @@ var init_bridge_flow_runner = __esm({
|
|
|
37867
37865
|
}
|
|
37868
37866
|
if (state?.state !== "home" || state.activeApp != null) return false;
|
|
37869
37867
|
const appId = this.resolveShellLaunchAppId(opts, state);
|
|
37870
|
-
if (this.recordingEnabled) {
|
|
37871
|
-
await this.ensureRecordingStarted();
|
|
37872
|
-
}
|
|
37873
37868
|
await callShellCommandWhenReady(this.bridge, "launchApp", 1e3, appId);
|
|
37874
37869
|
await this.waitForShellAppLaunched(appId, 1e3);
|
|
37875
37870
|
return true;
|
package/dist-lib/vite.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.489 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
package/package.json
CHANGED
|
@@ -95,7 +95,7 @@ export class AgentDaemonClient {
|
|
|
95
95
|
constructor(opts: AgentDaemonClientOptions = {}) {
|
|
96
96
|
this.port = opts.port ?? DEFAULT_SOOTSIM_BRIDGE_PORT
|
|
97
97
|
this.commandTimeoutMs = opts.commandTimeoutMs ?? 15_000
|
|
98
|
-
this.ws = new WebSocket(`ws://
|
|
98
|
+
this.ws = new WebSocket(`ws://127.0.0.1:${this.port}`)
|
|
99
99
|
this.ready = new Promise<void>((resolve, reject) => {
|
|
100
100
|
const onOpen = () => {
|
|
101
101
|
this.ws.off('error', onError)
|
package/src/bridge-constants.ts
CHANGED
|
@@ -148,8 +148,13 @@ export function resolveSootsimBridgeWebSocketUrl(input: {
|
|
|
148
148
|
bridgePort: number
|
|
149
149
|
href: string
|
|
150
150
|
}): string {
|
|
151
|
+
// 127.0.0.1, not localhost. the daemon binds ipv4 only (bridge-host bindOnce)
|
|
152
|
+
// so that localhost's ::1/127.0.0.1 coinflip cannot hide it; the health probe
|
|
153
|
+
// already talks to 127.0.0.1. targeting localhost here undoes that: when node
|
|
154
|
+
// tries ::1 first and does not fall back, vite's proxy answers 502 and the
|
|
155
|
+
// browser logs a console error that fails e2e.
|
|
151
156
|
return resolveSootsimWebSocketProxyUrl({
|
|
152
|
-
targetUrl: `ws://
|
|
157
|
+
targetUrl: `ws://127.0.0.1:${input.bridgePort}`,
|
|
153
158
|
href: input.href,
|
|
154
159
|
})
|
|
155
160
|
}
|