peachsim 0.1.527

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (324) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +640 -0
  3. package/cli/app-config.ts +82 -0
  4. package/cli/app-fonts.ts +388 -0
  5. package/cli/app-project.ts +59 -0
  6. package/cli/app-splash.ts +171 -0
  7. package/cli/app-state-reset.ts +26 -0
  8. package/cli/auth.ts +184 -0
  9. package/cli/bin.ts +59 -0
  10. package/cli/bridge-diagnostics.ts +226 -0
  11. package/cli/bridge-flow-runner.ts +2806 -0
  12. package/cli/browser-backend.ts +44 -0
  13. package/cli/browser-evals.ts +96 -0
  14. package/cli/cli-update.ts +261 -0
  15. package/cli/cloud-client.ts +1530 -0
  16. package/cli/cloud-dispatch.ts +206 -0
  17. package/cli/cloud-session.ts +227 -0
  18. package/cli/command-contract.ts +221 -0
  19. package/cli/command-registry.ts +304 -0
  20. package/cli/commands/agent-wrapper.ts +1048 -0
  21. package/cli/commands/agent.ts +439 -0
  22. package/cli/commands/app-fonts.ts +99 -0
  23. package/cli/commands/assert.ts +542 -0
  24. package/cli/commands/auth.ts +71 -0
  25. package/cli/commands/box/bundle-plane.ts +71 -0
  26. package/cli/commands/box/checkout-plane.ts +256 -0
  27. package/cli/commands/box/plane-share.ts +208 -0
  28. package/cli/commands/box/rnx-command.ts +60 -0
  29. package/cli/commands/box/search-command.ts +157 -0
  30. package/cli/commands/box.ts +925 -0
  31. package/cli/commands/camera.ts +266 -0
  32. package/cli/commands/cleanup.ts +169 -0
  33. package/cli/commands/compat.ts +176 -0
  34. package/cli/commands/config.ts +34 -0
  35. package/cli/commands/control.ts +2154 -0
  36. package/cli/commands/cpu-profile.ts +941 -0
  37. package/cli/commands/daemon-mac-app.ts +165 -0
  38. package/cli/commands/daemon.ts +800 -0
  39. package/cli/commands/debug.ts +751 -0
  40. package/cli/commands/desktop.ts +39 -0
  41. package/cli/commands/detect.ts +201 -0
  42. package/cli/commands/detox.ts +481 -0
  43. package/cli/commands/device.ts +134 -0
  44. package/cli/commands/diagnose.ts +589 -0
  45. package/cli/commands/do-chain.ts +408 -0
  46. package/cli/commands/electron.ts +94 -0
  47. package/cli/commands/film.ts +379 -0
  48. package/cli/commands/flow.ts +1240 -0
  49. package/cli/commands/inspect/actions.ts +516 -0
  50. package/cli/commands/inspect/core.ts +2086 -0
  51. package/cli/commands/inspect/count.ts +17 -0
  52. package/cli/commands/inspect/describe.ts +119 -0
  53. package/cli/commands/inspect/env.ts +25 -0
  54. package/cli/commands/inspect/find.ts +169 -0
  55. package/cli/commands/inspect/get-layout.ts +53 -0
  56. package/cli/commands/inspect/keyboard.ts +54 -0
  57. package/cli/commands/inspect/list.ts +175 -0
  58. package/cli/commands/inspect/memory.ts +215 -0
  59. package/cli/commands/inspect/redaction.ts +39 -0
  60. package/cli/commands/inspect/resolve-target.ts +77 -0
  61. package/cli/commands/inspect/screens.ts +78 -0
  62. package/cli/commands/inspect/settle.ts +32 -0
  63. package/cli/commands/inspect/settling.ts +197 -0
  64. package/cli/commands/inspect/shared.ts +259 -0
  65. package/cli/commands/inspect/sleep.ts +15 -0
  66. package/cli/commands/inspect/tree.ts +23 -0
  67. package/cli/commands/inspect/url.ts +17 -0
  68. package/cli/commands/inspect/wait-event.ts +211 -0
  69. package/cli/commands/inspect/wait-idle.ts +25 -0
  70. package/cli/commands/inspect/wait-ready.ts +87 -0
  71. package/cli/commands/inspect/wait-selector.ts +59 -0
  72. package/cli/commands/inspect/wait.ts +32 -0
  73. package/cli/commands/inspect.ts +4738 -0
  74. package/cli/commands/install-cli.ts +275 -0
  75. package/cli/commands/install-desktop.ts +385 -0
  76. package/cli/commands/login.ts +357 -0
  77. package/cli/commands/logout.ts +24 -0
  78. package/cli/commands/maestro-generate.ts +375 -0
  79. package/cli/commands/maestro.ts +536 -0
  80. package/cli/commands/mode.ts +58 -0
  81. package/cli/commands/no-bridge-hint.ts +80 -0
  82. package/cli/commands/perf.ts +67 -0
  83. package/cli/commands/permissions.ts +203 -0
  84. package/cli/commands/platform.ts +410 -0
  85. package/cli/commands/preview.ts +103 -0
  86. package/cli/commands/profile.ts +106 -0
  87. package/cli/commands/react.ts +353 -0
  88. package/cli/commands/record.ts +1435 -0
  89. package/cli/commands/report-issue.ts +305 -0
  90. package/cli/commands/reset.ts +89 -0
  91. package/cli/commands/runtime.ts +348 -0
  92. package/cli/commands/screenshot-command.ts +106 -0
  93. package/cli/commands/screenshot-layers.ts +144 -0
  94. package/cli/commands/screenshot-mode.ts +38 -0
  95. package/cli/commands/screenshot.ts +492 -0
  96. package/cli/commands/screenshots-capture.ts +608 -0
  97. package/cli/commands/screenshots.ts +127 -0
  98. package/cli/commands/serve.ts +139 -0
  99. package/cli/commands/setup.ts +416 -0
  100. package/cli/commands/shell-boolean-mode.ts +82 -0
  101. package/cli/commands/skills.ts +468 -0
  102. package/cli/commands/slides.ts +357 -0
  103. package/cli/commands/state.ts +94 -0
  104. package/cli/commands/storage.ts +58 -0
  105. package/cli/commands/telemetry.ts +55 -0
  106. package/cli/commands/test.ts +535 -0
  107. package/cli/commands/three-mode.ts +771 -0
  108. package/cli/commands/timeline.ts +121 -0
  109. package/cli/commands/upgrade.ts +167 -0
  110. package/cli/commands/upload.ts +1203 -0
  111. package/cli/commands/version.ts +63 -0
  112. package/cli/commands/welcome.ts +17 -0
  113. package/cli/commands/what-happened.ts +328 -0
  114. package/cli/current-sim.ts +217 -0
  115. package/cli/desktop-companion.ts +315 -0
  116. package/cli/drivers/electron.ts +70 -0
  117. package/cli/drivers/index.ts +20 -0
  118. package/cli/drivers/playwright-provisioning.ts +184 -0
  119. package/cli/drivers/playwright-sim-host.ts +537 -0
  120. package/cli/drivers/playwright.ts +209 -0
  121. package/cli/drivers/registry.ts +65 -0
  122. package/cli/drivers/types.ts +102 -0
  123. package/cli/flow-export.ts +55 -0
  124. package/cli/flow-file.ts +142 -0
  125. package/cli/flow-live-status.ts +126 -0
  126. package/cli/flow-session.ts +140 -0
  127. package/cli/help-core.ts +143 -0
  128. package/cli/help.ts +44 -0
  129. package/cli/hidden-runtime-alias.ts +19 -0
  130. package/cli/hints.ts +214 -0
  131. package/cli/inspect-notice-state.ts +114 -0
  132. package/cli/internal-child.ts +176 -0
  133. package/cli/maestro-js.ts +323 -0
  134. package/cli/main.ts +704 -0
  135. package/cli/open-url.ts +8 -0
  136. package/cli/outbound-endpoints.ts +830 -0
  137. package/cli/parent-pid.ts +204 -0
  138. package/cli/parse-args.ts +189 -0
  139. package/cli/privacy.ts +53 -0
  140. package/cli/prompt.ts +56 -0
  141. package/cli/recording-access.ts +108 -0
  142. package/cli/registry.ts +2 -0
  143. package/cli/resolve-assets.ts +63 -0
  144. package/cli/rnx-in-process.ts +98 -0
  145. package/cli/run-registry.ts +226 -0
  146. package/cli/run-rnx-core.ts +148 -0
  147. package/cli/run-rnx.ts +137 -0
  148. package/cli/runtime-notes.ts +66 -0
  149. package/cli/runtime-summary.ts +25 -0
  150. package/cli/secure-file.ts +31 -0
  151. package/cli/self-invocation.ts +58 -0
  152. package/cli/send-to-box.ts +109 -0
  153. package/cli/setup-repository.ts +191 -0
  154. package/cli/shell-init.ts +98 -0
  155. package/cli/standalone.ts +4 -0
  156. package/cli/telemetry.ts +84 -0
  157. package/cli/ui.ts +68 -0
  158. package/cli/ws-bridge.ts +1020 -0
  159. package/detox/attempt-events.cjs +23 -0
  160. package/detox/colors.ts +54 -0
  161. package/detox/config-loader.ts +135 -0
  162. package/detox/element-types.ts +48 -0
  163. package/detox/expectations.ts +534 -0
  164. package/detox/gestures.ts +501 -0
  165. package/detox/index.ts +2694 -0
  166. package/detox/jest-preset.cjs +29 -0
  167. package/detox/jest-setup-after-env.cjs +22 -0
  168. package/detox/matchers.ts +30 -0
  169. package/detox/motion-change.cjs +109 -0
  170. package/detox/motion-change.d.cts +35 -0
  171. package/detox/navigation-lifecycle.ts +290 -0
  172. package/detox/navigation.ts +43 -0
  173. package/detox/proof-frame.cjs +114 -0
  174. package/detox/record-block-execution.cjs +78 -0
  175. package/detox/screenshots/animated-color-test-rest-norngh.png +0 -0
  176. package/detox/screenshots/color-test-after-drag-norngh.png +0 -0
  177. package/detox/screenshots/color-test-rest-norngh.png +0 -0
  178. package/detox/screenshots/theme-blue-toggle.png +0 -0
  179. package/detox/screenshots/theme-blue.png +0 -0
  180. package/detox/screenshots/theme-red-toggle.png +0 -0
  181. package/detox/screenshots/theme-red.png +0 -0
  182. package/dist-lib/agent-daemon-client.cjs +502 -0
  183. package/dist-lib/agent-events.cjs +48 -0
  184. package/dist-lib/agent-identity.cjs +53 -0
  185. package/dist-lib/agent-sessions.cjs +759 -0
  186. package/dist-lib/attached-projects.cjs +526 -0
  187. package/dist-lib/auth/shared-session.cjs +208 -0
  188. package/dist-lib/backend-origin.cjs +88 -0
  189. package/dist-lib/beta.cjs +41 -0
  190. package/dist-lib/beta.mjs +13 -0
  191. package/dist-lib/bridge-constants.cjs +161 -0
  192. package/dist-lib/bridge-contract-input.cjs +451 -0
  193. package/dist-lib/bridge-contract-input.mjs +414 -0
  194. package/dist-lib/bridge-contract.cjs +130 -0
  195. package/dist-lib/bridge-contract.mjs +94 -0
  196. package/dist-lib/capture-contract.cjs +220 -0
  197. package/dist-lib/capture-contract.mjs +190 -0
  198. package/dist-lib/cli-constants.cjs +32 -0
  199. package/dist-lib/cloud-contract.cjs +194 -0
  200. package/dist-lib/cloud-contract.mjs +145 -0
  201. package/dist-lib/cloud.cjs +670 -0
  202. package/dist-lib/cloud.mjs +639 -0
  203. package/dist-lib/config.cjs +96 -0
  204. package/dist-lib/detox/index.cjs +3789 -0
  205. package/dist-lib/detox/jest-preset.cjs +29 -0
  206. package/dist-lib/dev-bundle-resolution.cjs +290 -0
  207. package/dist-lib/home-paths.cjs +638 -0
  208. package/dist-lib/host/bridge-host.cjs +10903 -0
  209. package/dist-lib/host/fetch-proxy-handler.cjs +421 -0
  210. package/dist-lib/host/fetch-proxy-overrides.cjs +63 -0
  211. package/dist-lib/host/fetch-proxy-overrides.mjs +37 -0
  212. package/dist-lib/host/replacement-module-handler.cjs +469 -0
  213. package/dist-lib/host/websocket-proxy.cjs +298 -0
  214. package/dist-lib/index.cjs +4268 -0
  215. package/dist-lib/jump-to-source-babel.cjs +93 -0
  216. package/dist-lib/jump-to-source-native.cjs +112 -0
  217. package/dist-lib/menu.cjs +646 -0
  218. package/dist-lib/menu.mjs +604 -0
  219. package/dist-lib/metro-fingerprint-registry.cjs +186 -0
  220. package/dist-lib/metro-fingerprint-registry.mjs +156 -0
  221. package/dist-lib/metro-production-bundle.cjs +329 -0
  222. package/dist-lib/metro-production-bundle.mjs +295 -0
  223. package/dist-lib/metro.cjs +904 -0
  224. package/dist-lib/profiles.cjs +246 -0
  225. package/dist-lib/public-brand.cjs +39 -0
  226. package/dist-lib/react-native-host-modules.cjs +51 -0
  227. package/dist-lib/react-native-host-modules.mjs +25 -0
  228. package/dist-lib/render-mode.cjs +54 -0
  229. package/dist-lib/scripts/dev-server-scanner.cjs +1232 -0
  230. package/dist-lib/sdk.cjs +2433 -0
  231. package/dist-lib/sdk.mjs +2336 -0
  232. package/dist-lib/skills.cjs +39132 -0
  233. package/dist-lib/swift-submit.cjs +92 -0
  234. package/dist-lib/swift-submit.mjs +65 -0
  235. package/dist-lib/swift.cjs +1646 -0
  236. package/dist-lib/vite.cjs +1591 -0
  237. package/package.json +290 -0
  238. package/scripts/dev-server-scanner.ts +1291 -0
  239. package/scripts/optional-demo-registry.ts +113 -0
  240. package/skills/contrast/SKILL.md +165 -0
  241. package/skills/rnx-debug/SKILL.md +433 -0
  242. package/skills/rnx-perf/SKILL.md +399 -0
  243. package/skills/rnx-setup/SKILL.md +172 -0
  244. package/skills/rnx-test/SKILL.md +321 -0
  245. package/skills/rnx-visual/SKILL.md +126 -0
  246. package/src/agent-daemon-client.ts +410 -0
  247. package/src/agent-events.ts +71 -0
  248. package/src/agent-identity.ts +23 -0
  249. package/src/agent-prompt.ts +71 -0
  250. package/src/agent-sessions.ts +580 -0
  251. package/src/app-url.ts +39 -0
  252. package/src/attached-projects.ts +539 -0
  253. package/src/auth/shared-session.ts +235 -0
  254. package/src/backend-origin.ts +70 -0
  255. package/src/beta.ts +19 -0
  256. package/src/bridge-constants.ts +175 -0
  257. package/src/bridge-contract-input.ts +502 -0
  258. package/src/bridge-contract.ts +558 -0
  259. package/src/browser-cache.ts +16 -0
  260. package/src/capture-contract.ts +587 -0
  261. package/src/cli-constants.ts +1 -0
  262. package/src/cli-version.ts +40 -0
  263. package/src/cloud-contract.ts +274 -0
  264. package/src/cloud.ts +762 -0
  265. package/src/codex-client.ts +234 -0
  266. package/src/config.ts +132 -0
  267. package/src/connect.ts +101 -0
  268. package/src/dev-bundle-resolution.ts +346 -0
  269. package/src/dev-server-open.ts +198 -0
  270. package/src/disk-cleanup.ts +540 -0
  271. package/src/flow-timeout-scale.ts +15 -0
  272. package/src/home-paths.ts +806 -0
  273. package/src/host/agent-host.ts +666 -0
  274. package/src/host/bridge-host.ts +2788 -0
  275. package/src/host/fetch-proxy-handler.ts +449 -0
  276. package/src/host/fetch-proxy-overrides.ts +51 -0
  277. package/src/host/open-url.ts +89 -0
  278. package/src/host/plane-host.ts +203 -0
  279. package/src/host/replacement-module-handler.ts +158 -0
  280. package/src/host/websocket-proxy.ts +315 -0
  281. package/src/index.ts +71 -0
  282. package/src/jump-to-source-babel.ts +135 -0
  283. package/src/jump-to-source-native.ts +102 -0
  284. package/src/menu.ts +777 -0
  285. package/src/metro-fingerprint-registry.ts +302 -0
  286. package/src/metro-plugin.ts +341 -0
  287. package/src/metro-production-bundle.ts +471 -0
  288. package/src/native-dev-bundle-url.ts +118 -0
  289. package/src/native-seam-manifest.ts +341 -0
  290. package/src/playwright-host-log.ts +16 -0
  291. package/src/plist.ts +27 -0
  292. package/src/poll-until.ts +123 -0
  293. package/src/profiles.ts +179 -0
  294. package/src/public-brand.ts +9 -0
  295. package/src/react-native-host-modules.ts +26 -0
  296. package/src/render-mode.ts +27 -0
  297. package/src/rolldown-plugin-swift.ts +240 -0
  298. package/src/runtime-assets.ts +233 -0
  299. package/src/runtime-delivery.ts +54 -0
  300. package/src/screenshots/compose.ts +422 -0
  301. package/src/screenshots/frame-compose.ts +514 -0
  302. package/src/screenshots/orchestrate.ts +256 -0
  303. package/src/screenshots/org-deck.ts +91 -0
  304. package/src/screenshots/registry.ts +58 -0
  305. package/src/screenshots/schema.ts +364 -0
  306. package/src/sdk.ts +15 -0
  307. package/src/settings-bundle.ts +418 -0
  308. package/src/shell-bridge-identity.ts +15 -0
  309. package/src/sim-client.ts +697 -0
  310. package/src/skills/builtin/a11y-review.ts +132 -0
  311. package/src/skills/builtin/compat-check.ts +71 -0
  312. package/src/skills/builtin/maestro-test.ts +121 -0
  313. package/src/skills/builtin/perf-profile.ts +90 -0
  314. package/src/skills/builtin/screenshot-all.ts +52 -0
  315. package/src/skills/builtin/visual-diff.ts +100 -0
  316. package/src/skills/registry.ts +107 -0
  317. package/src/skills/types.ts +41 -0
  318. package/src/swift-submit.ts +185 -0
  319. package/src/swift.ts +7 -0
  320. package/src/team-machine-prompt.ts +73 -0
  321. package/src/vite-plugin-one.ts +264 -0
  322. package/src/vite-plugin-swift.ts +620 -0
  323. package/src/vite-plugin.ts +1946 -0
  324. package/src/worklets-babel.ts +250 -0
@@ -0,0 +1,558 @@
1
+ // the wire contract for the sootsim ws bridge. the engine implements it in
2
+ // sootsim-engine/src/mcp/ws-bridge.ts; the rnxsim cli client, the SimClient
3
+ // sdk, and the flow runner speak it. it is the single owner of these shapes,
4
+ // and neither side redeclares them.
5
+ //
6
+ // it lives in rnxsim rather than the engine because rnxsim is published and
7
+ // sootsim-engine is `private: true`. the engine already depends on rnxsim
8
+ // (see its `rnxsim` dependency and its `rnxsim/bridge-constants` import), so
9
+ // this is the direction that ships.
10
+
11
+ import type {
12
+ SootSimAgentActionDetail,
13
+ SootSimCaptureFilter,
14
+ SootSimExternalAppLifecycleOptions,
15
+ SootSimStorageResetStrategy,
16
+ } from '@rnx/globals'
17
+
18
+ export type BridgeCommandType =
19
+ | 'evaluate'
20
+ | 'call'
21
+ | 'screenshot'
22
+ | 'capture'
23
+ | 'captureRegions'
24
+ | 'settle'
25
+ | 'setAppearance'
26
+ | 'openUrl'
27
+ | 'memory'
28
+ | 'tap'
29
+ | 'longPress'
30
+ | 'keyboard'
31
+ | 'tree'
32
+ | 'focus'
33
+ | 'close'
34
+ | 'flowStatus'
35
+ | 'perform'
36
+ | 'waitFor'
37
+ | 'state'
38
+ | 'query'
39
+ | 'resolve'
40
+ | 'reset'
41
+ | 'camera'
42
+ | 'diagnostics'
43
+ | 'storageSnapshot'
44
+
45
+ export interface WsCommand {
46
+ id: string | number
47
+ type: BridgeCommandType
48
+ // local daemon routing; cloud transport strips it before execution.
49
+ simId?: string
50
+ // flowStatus — live flow-runner progress payload (see flow-run-store)
51
+ status?: Record<string, unknown>
52
+ code?: string
53
+ path?: string
54
+ args?: unknown[]
55
+ x?: number
56
+ y?: number
57
+ durationMs?: number
58
+ maxFrames?: number
59
+ target?: SootSimAgentActionDetail['target']
60
+ action?: string
61
+ text?: string
62
+ appearance?: 'light' | 'dark'
63
+ url?: string
64
+ includeVisual?: boolean
65
+ includeFonts?: boolean
66
+ includeRasterAtlas?: boolean
67
+ regions?: import('./capture-contract').RnxCaptureRegionRequest[]
68
+ depth?: number
69
+ // screenshot — which canvas layers to composite. omit for full (today's
70
+ // default: everything including iOS chrome). 'tenant' excludes the shell
71
+ // overlay for a clean app capture.
72
+ layers?: 'full' | 'tenant' | 'shell'
73
+ // screenshot — engine-side layer isolation (hide subtrees / solo one
74
+ // subtree on transparency). see SootSimCaptureOptions.captureFilter.
75
+ captureFilter?: SootSimCaptureFilter
76
+ // screenshot — optional crop rect in logical sootsim coords. the capture
77
+ // module scales x/y/w/h by device pixel ratio before cropping.
78
+ crop?: { x: number; y: number; w: number; h: number }
79
+ // perform — ordered batch executed inside the page, no round trips
80
+ steps?: PerformStep[]
81
+ performOptions?: PerformOptions
82
+ // waitFor — one engine-side polling loop and one transport round trip
83
+ waitForOptions?: SemanticWaitOptions
84
+ // state — compound screenshot + tree + route + errors
85
+ stateOptions?: SimStateOptions
86
+ // query / resolve — structured visible-tree reads and selector geometry
87
+ query?: SimSemanticQuery
88
+ selector?: SimSemanticResolveSelector
89
+ // reset — two-tier app state wipe
90
+ resetOptions?: ResetOptions
91
+ // camera — fixture injection into the host camera pipeline
92
+ camera?: CameraCommand
93
+ // diagnostics — read-only engine debug state: channel recording, the sheet /
94
+ // portal / boundary finders, and the recent event ring.
95
+ diagnostics?: DiagnosticsOptions
96
+ // storageSnapshot — the running app's own storage and route, as
97
+ // `StorageSnapshot` from the engine's preview/storage-snapshot module. the
98
+ // default result is share-safe; `includeCredentials` carries the signed-in
99
+ // session and belongs only to a send to the owner's own box.
100
+ storageSnapshotOptions?: { includeCredentials?: boolean }
101
+ }
102
+
103
+ // ---------------------------------------------------------------------------
104
+ // perform — batched input
105
+ // ---------------------------------------------------------------------------
106
+
107
+ // every step maps onto a primitive that already exists on
108
+ // SootSim.bridges.interact / .keyboard / .test. the batch runs entirely inside
109
+ // the page so gesture timing is real wall-clock timing, not ws round-trips.
110
+ //
111
+ // deliberately absent: text-based tap resolution. matching by visible text is
112
+ // fuzzy, needs ranking and failure diagnostics, and lives once in the cli's
113
+ // tapByText. the sdk resolves text to coordinates before it builds a batch.
114
+ // testID lookup is exact, so tapId resolves in-engine.
115
+ export type PerformStep =
116
+ // raw pointer steps — full control over gesture physics
117
+ | { type: 'touchDown'; x: number; y: number; pointerId?: number }
118
+ | { type: 'touchMove'; x: number; y: number; pointerId?: number }
119
+ | { type: 'touchUp'; x: number; y: number; pointerId?: number }
120
+ | { type: 'touchCancel'; pointerId?: number }
121
+ // semantic steps
122
+ | { type: 'tap'; x: number; y: number; target?: SootSimAgentActionDetail['target'] }
123
+ | { type: 'tapId'; id: string }
124
+ | { type: 'doubleTap'; x: number; y: number; gapMs?: number }
125
+ | {
126
+ type: 'longPress'
127
+ x: number
128
+ y: number
129
+ durationMs?: number
130
+ target?: SootSimAgentActionDetail['target']
131
+ }
132
+ | {
133
+ type: 'drag'
134
+ fromX: number
135
+ fromY: number
136
+ toX: number
137
+ toY: number
138
+ steps?: number
139
+ stepMs?: number
140
+ }
141
+ | {
142
+ type: 'pinch'
143
+ fromX1: number
144
+ fromY1: number
145
+ fromX2: number
146
+ fromY2: number
147
+ toX1: number
148
+ toY1: number
149
+ toX2: number
150
+ toY2: number
151
+ steps?: number
152
+ stepMs?: number
153
+ }
154
+ | { type: 'scroll'; id: string; x?: number; y?: number; animated?: boolean }
155
+ | { type: 'type'; text: string }
156
+ | { type: 'key'; key: string }
157
+ | { type: 'dismissKeyboard' }
158
+ | { type: 'wait'; ms: number }
159
+ | {
160
+ type: 'waitFor'
161
+ testID?: string
162
+ id?: string
163
+ condition?: 'present' | 'mounted' | 'absent'
164
+ timeoutMs?: number
165
+ }
166
+ // limrun parity steps. each maps onto an engine primitive and reports
167
+ // per step; the refused ones below parse but never run.
168
+ | { type: 'setElementValue'; id: string; text: string; submit?: boolean }
169
+ | { type: 'toggleKeyboard' }
170
+ | { type: 'openUrl'; url: string }
171
+ | { type: 'keyDown'; key: string }
172
+ | { type: 'keyUp'; key: string }
173
+ | { type: 'setOrientation'; orientation: 'portrait' | 'landscape' }
174
+ | { type: 'deviceInfo' }
175
+ // refused with a named reason, never emulated: no hardware-button model,
176
+ // no storekit simulation, no stepper primitive, and key/orientation state
177
+ // the engine does not hold.
178
+ | { type: 'buttonDown'; button?: string }
179
+ | { type: 'buttonUp'; button?: string }
180
+ | { type: 'incrementElement'; id: string }
181
+ | { type: 'decrementElement'; id: string }
182
+ | { type: 'discoverStoreKitConfig' }
183
+ | { type: 'clearStoreKitConfig' }
184
+
185
+ export interface PerformOptions {
186
+ // stop the batch at the first failing step. default true — a gesture whose
187
+ // touchDown missed should not keep dragging.
188
+ stopOnError?: boolean
189
+ // ceiling on batch PROGRESS, checked between steps: once it passes, the
190
+ // batch starts no further steps and reports which one it reached. a step
191
+ // already running is always awaited to completion, never abandoned, because
192
+ // a gesture that keeps dispatching pointer events after the caller has been
193
+ // told the batch failed is worse than a late reply. every step is bounded on
194
+ // its own (drag and pinch by steps * stepMs, wait by ms, waitFor by its own
195
+ // timeout), and a wedged worker is caught by the CLI client's per-command
196
+ // timeout one layer up. default 30000.
197
+ timeoutMs?: number
198
+ }
199
+
200
+ // observed device identity for the `deviceInfo` step: the live device spec
201
+ // in both runtimes, so every field is measured, never a default.
202
+ export interface PerformDeviceInfo {
203
+ platform: string
204
+ model?: string
205
+ width: number
206
+ height: number
207
+ scale: number
208
+ }
209
+
210
+ // steps that parse but never run. one owner for the refusal vocabulary so
211
+ // the browser page and the cpu runtime refuse with the same named reason and
212
+ // neither plane emulates what the engine cannot do.
213
+ export const REFUSED_PERFORM_STEP_TYPES = [
214
+ 'keyDown',
215
+ 'keyUp',
216
+ 'setOrientation',
217
+ 'buttonDown',
218
+ 'buttonUp',
219
+ 'incrementElement',
220
+ 'decrementElement',
221
+ 'discoverStoreKitConfig',
222
+ 'clearStoreKitConfig',
223
+ ] as const
224
+
225
+ export type RefusedPerformStepType = (typeof REFUSED_PERFORM_STEP_TYPES)[number]
226
+
227
+ export function refusedPerformStepReason(type: RefusedPerformStepType): string {
228
+ switch (type) {
229
+ case 'keyDown':
230
+ case 'keyUp':
231
+ return `${type} is not supported: keys dispatch atomically; use the key step`
232
+ case 'setOrientation':
233
+ return 'setOrientation is not supported: the simulator viewport is fixed at boot'
234
+ case 'buttonDown':
235
+ case 'buttonUp':
236
+ return `${type} is not supported: the simulator has no hardware buttons`
237
+ case 'incrementElement':
238
+ case 'decrementElement':
239
+ return `${type} is not supported: steppers have no engine primitive; drive them with tapId`
240
+ case 'discoverStoreKitConfig':
241
+ case 'clearStoreKitConfig':
242
+ return `${type} is not supported: storekit has no simulator model`
243
+ }
244
+ }
245
+
246
+ // returns the refusal for a refused step, null when the step is runnable.
247
+ // every variant is listed so adding a step forces its classification here;
248
+ // the executors mirror the refused cases in their own switches.
249
+ export function performStepRefusal(type: PerformStep['type']): string | null {
250
+ switch (type) {
251
+ case 'keyDown':
252
+ case 'keyUp':
253
+ case 'setOrientation':
254
+ case 'buttonDown':
255
+ case 'buttonUp':
256
+ case 'incrementElement':
257
+ case 'decrementElement':
258
+ case 'discoverStoreKitConfig':
259
+ case 'clearStoreKitConfig':
260
+ return refusedPerformStepReason(type)
261
+ case 'touchDown':
262
+ case 'touchMove':
263
+ case 'touchUp':
264
+ case 'touchCancel':
265
+ case 'tap':
266
+ case 'tapId':
267
+ case 'doubleTap':
268
+ case 'longPress':
269
+ case 'drag':
270
+ case 'pinch':
271
+ case 'scroll':
272
+ case 'type':
273
+ case 'key':
274
+ case 'dismissKeyboard':
275
+ case 'setElementValue':
276
+ case 'toggleKeyboard':
277
+ case 'openUrl':
278
+ case 'deviceInfo':
279
+ case 'wait':
280
+ case 'waitFor':
281
+ return null
282
+ }
283
+ }
284
+
285
+ export interface PerformStepResult {
286
+ index: number
287
+ type: PerformStep['type']
288
+ ok: boolean
289
+ // step-specific payload: tap hit info, waitFor match, resolved coordinates
290
+ value?: unknown
291
+ error?: string
292
+ // wall-clock ms this step took inside the page
293
+ durationMs: number
294
+ }
295
+
296
+ export interface PerformResult {
297
+ ok: boolean
298
+ steps: PerformStepResult[]
299
+ // number of steps that ran. less than steps.length when the batch aborted.
300
+ completed: number
301
+ durationMs: number
302
+ error?: string
303
+ }
304
+
305
+ // ---------------------------------------------------------------------------
306
+ // waitFor — engine-side semantic condition polling
307
+ // ---------------------------------------------------------------------------
308
+
309
+ // `present` is what a person can see: the node must survive the occlusion pass,
310
+ // so a button behind a sheet does not count. `mounted` asks only whether the
311
+ // node exists and is laid out, which is the right question for a marker the app
312
+ // renders as proof of something (a build id, a launch phase) rather than as
313
+ // something to look at — those are 1x1 and painted under the whole app, so they
314
+ // are permanently occluded and `present` can never match one.
315
+ export type SemanticWaitCondition =
316
+ | { type: 'ready' }
317
+ | { type: 'present'; selector: SimSemanticResolveSelector }
318
+ | { type: 'mounted'; selector: SimSemanticResolveSelector }
319
+ | { type: 'absent'; selector: SimSemanticResolveSelector }
320
+
321
+ export interface SemanticWaitOptions {
322
+ condition: SemanticWaitCondition
323
+ timeoutMs?: number
324
+ }
325
+
326
+ export interface SemanticReadyProbe {
327
+ flag: unknown
328
+ at: number
329
+ nodes: number
330
+ targets: number
331
+ liveFrameActive: boolean
332
+ liveFrameChannels: number
333
+ liveFramePublishes: number
334
+ errors: number
335
+ loadingText: string
336
+ externalReady: boolean | null
337
+ externalStatus: string
338
+ externalError: string
339
+ suppressedEntryError: string
340
+ }
341
+
342
+ // react native's own Pressable/Touchable delayLongPress default, and the
343
+ // ceiling any transport accepts for a press-and-hold. a driver that holds
344
+ // longer than this is describing a drag, not a long press.
345
+ export const SIM_LONG_PRESS_DEFAULT_MS = 500
346
+ export const SIM_LONG_PRESS_MAX_MS = 5_000
347
+
348
+ export const SEMANTIC_READY_CONTENT_NODE_FLOOR = 100
349
+ export const SEMANTIC_READY_NODE_STABLE_MS = 750
350
+ export const SEMANTIC_READY_POLL_MS = 150
351
+
352
+ export const PUBLIC_NO_NETWORK_MARKER = 'public RNX Cloud simulators have no network'
353
+ export const HEADLESS_TENANT_FETCH_HUNG_MARKER = 'headless tenant fetch hung'
354
+
355
+ export function readyProbeHasContent(
356
+ probe: Pick<SemanticReadyProbe, 'nodes' | 'targets'> &
357
+ Partial<Pick<SemanticReadyProbe, 'liveFrameActive'>>,
358
+ ): boolean {
359
+ return (
360
+ probe.liveFrameActive ||
361
+ probe.targets > 0 ||
362
+ probe.nodes >= SEMANTIC_READY_CONTENT_NODE_FLOOR
363
+ )
364
+ }
365
+
366
+ export function readyProbeHasTargetContent(
367
+ probe: Pick<SemanticReadyProbe, 'targets'> &
368
+ Partial<Pick<SemanticReadyProbe, 'liveFrameActive'>>,
369
+ ): boolean {
370
+ return probe.liveFrameActive || probe.targets > 0
371
+ }
372
+
373
+ export interface SemanticWaitResult {
374
+ matched: boolean
375
+ elapsedMs: number
376
+ polls: number
377
+ probe?: SemanticReadyProbe
378
+ node?: SimSemanticNode
379
+ error?: string
380
+ }
381
+
382
+ // ---------------------------------------------------------------------------
383
+ // state — one round-trip situational awareness
384
+ // ---------------------------------------------------------------------------
385
+
386
+ export interface DiagnosticsOptions {
387
+ // debug channels to record from this point on. omitted leaves recording as
388
+ // it is; an empty list stops recording.
389
+ channels?: readonly string[]
390
+ find?: 'sheets' | 'portals' | 'boundaries'
391
+ recentChannel?: string
392
+ recentLimit?: number
393
+ }
394
+
395
+ export interface DiagnosticsResult {
396
+ channels: string[]
397
+ runtime: unknown
398
+ found: unknown[] | null
399
+ events: unknown[]
400
+ }
401
+
402
+ export interface SimStateOptions {
403
+ // omit a section an agent does not need this turn
404
+ screenshot?: boolean
405
+ tree?: boolean
406
+ route?: boolean
407
+ errors?: boolean
408
+ // include the bounded guest console tail. omitted by the ordinary state
409
+ // command so one-shot state remains compact; `rnx logs` requests it.
410
+ logs?: boolean
411
+ // tree depth, matching the standalone `tree` command. default 5.
412
+ depth?: number
413
+ layers?: WsCommand['layers']
414
+ // cap on recentErrors entries. default 20.
415
+ errorLimit?: number
416
+ // cap on recentLogs entries. default and maximum 100.
417
+ logLimit?: number
418
+ }
419
+
420
+ export interface SimStateLogEntry {
421
+ level: string
422
+ text: string
423
+ at?: number
424
+ }
425
+
426
+ export interface SimStateResult {
427
+ // png data uri, same encoding the `screenshot` command returns
428
+ screenshot?: unknown
429
+ tree?: SimSemanticNode[]
430
+ route?: { url?: string; screen?: string | null; stack?: string[] } | null
431
+ recentErrors?: SimStateLogEntry[]
432
+ recentLogs?: SimStateLogEntry[]
433
+ keyboard?: { visible: boolean; mode?: string | null }
434
+ capturedAt: number
435
+ }
436
+
437
+ // ---------------------------------------------------------------------------
438
+ // semantic tree — pruned visible structure shared by local and cloud runtimes
439
+ // ---------------------------------------------------------------------------
440
+
441
+ export interface SimSemanticGeometry {
442
+ x: number
443
+ y: number
444
+ width: number
445
+ height: number
446
+ }
447
+
448
+ export interface SimSemanticNode {
449
+ nodeId: number
450
+ type: string
451
+ testID?: string
452
+ text?: string
453
+ role?: string
454
+ label?: string
455
+ pressable?: true
456
+ geometry: SimSemanticGeometry
457
+ children?: SimSemanticNode[]
458
+ }
459
+
460
+ export type SimSemanticSelector =
461
+ | { testID: string }
462
+ | { text: string }
463
+ | { role: string }
464
+ | { type: string }
465
+ | { pressable: true }
466
+ | { visible: true }
467
+
468
+ export type SimSemanticQuery =
469
+ | { kind: 'tree'; depth?: number }
470
+ | { kind: 'find'; selector: SimSemanticSelector }
471
+ | { kind: 'count' }
472
+
473
+ export interface SimSemanticQueryResult {
474
+ nodes: SimSemanticNode[]
475
+ total: number
476
+ }
477
+
478
+ export type SimSemanticResolveSelector = { testID: string } | { text: string }
479
+
480
+ export interface SimSemanticResolveResult {
481
+ match: SimSemanticNode
482
+ target: SimSemanticNode
483
+ point: { x: number; y: number }
484
+ }
485
+
486
+ // ---------------------------------------------------------------------------
487
+ // reset — two-tier app state wipe
488
+ // ---------------------------------------------------------------------------
489
+
490
+ // 'data' clears what a user could clear from inside the app: async storage,
491
+ // MMKV, sqlite, cache dirs. 'full' also clears what only a fresh install would:
492
+ // simulated keychain, user defaults, granted permissions.
493
+ //
494
+ // reset replaces the tenant worker before clearing storage, so background app
495
+ // work cannot refill a store between its clear and verification.
496
+ export type ResetStrategy = SootSimStorageResetStrategy
497
+
498
+ export interface ResetOptions extends Pick<
499
+ SootSimExternalAppLifecycleOptions,
500
+ 'initialUrl' | 'launchArguments'
501
+ > {
502
+ strategy?: ResetStrategy
503
+ // relaunch the app after wiping. default true.
504
+ relaunch?: boolean
505
+ // boot the wiped simulator on a live copy of another simulator's storage
506
+ // instead of empty stores: the cheap clean-but-not-cold seam. the id names
507
+ // a simulator on the same account; runtimes that cannot reach another
508
+ // simulator's storage refuse it by name rather than wiping without forking.
509
+ from?: string
510
+ }
511
+
512
+ export interface ResetResult {
513
+ ok: boolean
514
+ strategy: ResetStrategy
515
+ // stores verified empty after the wipe, read back rather than assumed
516
+ cleared: string[]
517
+ // stores this strategy deliberately did NOT clear, each with the reason.
518
+ // a named gap is not a failure, so this leaves `ok` true and stays out of
519
+ // `error`; a caller that cares can branch on it.
520
+ skipped?: Array<{ store: string; reason: string }>
521
+ relaunched: boolean
522
+ // true when reset had to restart the tenant worker instead of doing an
523
+ // in-worker cold remount. a restart is correct but slow, so a caller running
524
+ // reset between tests needs to see which path it got.
525
+ workerReloaded?: boolean
526
+ error?: string
527
+ }
528
+
529
+ // ---------------------------------------------------------------------------
530
+ // camera — fixture injection
531
+ // ---------------------------------------------------------------------------
532
+
533
+ // the host thread owns the camera pipeline (hidden <video> -> <canvas> ->
534
+ // ImageBitmap -> worker). injection replaces the source of that <video>, so
535
+ // every downstream consumer — expo-camera's live frame texture and the
536
+ // BarcodeDetector scan loop — sees the fixture with no seam of its own.
537
+ export interface CameraPlayOptions {
538
+ // url the host can fetch. the cli serves the local file from the daemon.
539
+ url: string
540
+ loop?: boolean
541
+ // playback rate, for making a slow fixture scan faster in ci
542
+ rate?: number
543
+ }
544
+
545
+ export type CameraCommand =
546
+ | ({ action: 'play' } & CameraPlayOptions)
547
+ | { action: 'stop' }
548
+ | { action: 'status' }
549
+
550
+ export interface CameraResult {
551
+ ok: boolean
552
+ // 'live' = real getUserMedia, 'fixture' = injected video, 'idle' = no session
553
+ source: 'live' | 'fixture' | 'idle'
554
+ url?: string
555
+ loop?: boolean
556
+ rate?: number
557
+ error?: string
558
+ }
@@ -0,0 +1,16 @@
1
+ export const DISPOSABLE_BROWSER_CACHE_DIR_NAMES = [
2
+ 'Cache',
3
+ 'Code Cache',
4
+ 'DawnCache',
5
+ 'DawnGraphiteCache',
6
+ 'DawnWebGPUCache',
7
+ 'GPUCache',
8
+ 'GrShaderCache',
9
+ 'ShaderCache',
10
+ ] as const
11
+
12
+ const disposableBrowserCacheDirs = new Set<string>(DISPOSABLE_BROWSER_CACHE_DIR_NAMES)
13
+
14
+ export function isDisposableBrowserCacheDir(name: string): boolean {
15
+ return disposableBrowserCacheDirs.has(name)
16
+ }