rnxsim 0.1.431 → 0.1.433

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 (78) hide show
  1. package/README.md +20 -50
  2. package/cli/auth.ts +33 -3
  3. package/cli/cloud-client.ts +524 -88
  4. package/cli/cloud-dispatch.ts +5 -10
  5. package/cli/cloud-session.ts +5 -5
  6. package/cli/commands/auth.ts +13 -2
  7. package/cli/commands/box.ts +189 -20
  8. package/cli/commands/control.ts +40 -13
  9. package/cli/commands/device.ts +1 -1
  10. package/cli/commands/flow.ts +189 -43
  11. package/cli/commands/inspect/get-layout.ts +1 -1
  12. package/cli/commands/inspect.ts +8 -1
  13. package/cli/commands/login.ts +79 -14
  14. package/cli/commands/maestro-generate.ts +70 -54
  15. package/cli/commands/maestro.ts +69 -20
  16. package/cli/commands/platform.ts +30 -32
  17. package/cli/commands/screenshot.ts +3 -2
  18. package/cli/commands/upload.ts +28 -10
  19. package/cli/help-core.ts +11 -1
  20. package/cli/outbound-endpoints.ts +27 -5
  21. package/cli/parse-args.ts +17 -0
  22. package/cli/shell-init.ts +4 -4
  23. package/cli/ws-bridge.ts +109 -62
  24. package/dist-lib/agent-daemon-client.cjs +1 -1
  25. package/dist-lib/agent-events.cjs +1 -1
  26. package/dist-lib/agent-identity.cjs +1 -1
  27. package/dist-lib/agent-sessions.cjs +1 -1
  28. package/dist-lib/attached-projects.cjs +1 -1
  29. package/dist-lib/auth/shared-session.cjs +17 -4
  30. package/dist-lib/backend-origin.cjs +1 -1
  31. package/dist-lib/beta.cjs +1 -1
  32. package/dist-lib/beta.mjs +1 -1
  33. package/dist-lib/bridge-constants.cjs +1 -1
  34. package/dist-lib/bridge-contract-input.cjs +1 -1
  35. package/dist-lib/bridge-contract-input.mjs +1 -1
  36. package/dist-lib/bridge-contract.cjs +1 -1
  37. package/dist-lib/bridge-contract.mjs +1 -1
  38. package/dist-lib/capture-contract.cjs +1 -1
  39. package/dist-lib/capture-contract.mjs +1 -1
  40. package/dist-lib/cli-constants.cjs +1 -1
  41. package/dist-lib/cloud-contract.cjs +1 -1
  42. package/dist-lib/cloud-contract.mjs +1 -1
  43. package/dist-lib/cloud.cjs +108 -93
  44. package/dist-lib/cloud.mjs +106 -91
  45. package/dist-lib/config.cjs +1 -1
  46. package/dist-lib/detox/index.cjs +1 -1
  47. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  48. package/dist-lib/home-paths.cjs +1 -1
  49. package/dist-lib/host/bridge-host.cjs +1 -1
  50. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  51. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  52. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  53. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  54. package/dist-lib/host/websocket-proxy.cjs +1 -1
  55. package/dist-lib/index.cjs +58 -139
  56. package/dist-lib/jump-to-source-babel.cjs +1 -1
  57. package/dist-lib/menu.cjs +1 -1
  58. package/dist-lib/menu.mjs +1 -1
  59. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  60. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  61. package/dist-lib/metro-production-bundle.cjs +1 -1
  62. package/dist-lib/metro-production-bundle.mjs +1 -1
  63. package/dist-lib/metro.cjs +33 -212
  64. package/dist-lib/profiles.cjs +1 -1
  65. package/dist-lib/public-brand.cjs +1 -1
  66. package/dist-lib/react-native-host-modules.cjs +1 -1
  67. package/dist-lib/react-native-host-modules.mjs +1 -1
  68. package/dist-lib/render-mode.cjs +1 -1
  69. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  70. package/dist-lib/sdk.cjs +1 -1
  71. package/dist-lib/sdk.mjs +1 -1
  72. package/dist-lib/skills.cjs +436 -351
  73. package/dist-lib/vite.cjs +1 -1
  74. package/package.json +2 -1
  75. package/src/auth/shared-session.ts +31 -0
  76. package/src/cloud.ts +83 -113
  77. package/src/metro-plugin.ts +30 -113
  78. package/src/vite-plugin.ts +11 -2
@@ -115,7 +115,7 @@ export const OUTBOUND_ENDPOINTS: Record<string, OutboundEndpointDeclaration> = {
115
115
  'https://rnxsim.com by default, or the test or disposable origin named by RNX_CLOUD_ORIGIN',
116
116
  preConsent: false,
117
117
  payload:
118
- 'the Metro JavaScript bundle selected by rnx ios --nano, then structured simulator commands and lifecycle requests',
118
+ 'the Metro JavaScript bundle selected by rnx ios --remote, then structured simulator commands and lifecycle requests',
119
119
  },
120
120
  }
121
121
 
@@ -152,8 +152,6 @@ export const DECLARED_OUTBOUND_CALLS: Record<string, OutboundCallDeclaration> =
152
152
  { category: 'rnx_cloud_sim', count: 1 },
153
153
  'packages/sootsim/src/cloud.ts :: fetch :: `${this.session.origin}/v1/sims/${encodeURIComponent(this.session.simId)}/claim`':
154
154
  { category: 'rnx_cloud_sim', count: 1 },
155
- 'packages/sootsim/src/cloud.ts :: fetch :: `${this.session.origin}/v1/boxes/${encodeURIComponent(this.session.boxId)}/simulators`':
156
- { category: 'rnx_cloud_sim', count: 1 },
157
155
  'packages/sootsim/src/cloud.ts :: fetch :: `${this.session.origin}/v1/boxes/${encodeURIComponent(this.session.boxId)}`':
158
156
  { category: 'rnx_cloud_sim', count: 1 },
159
157
  // maestro's flow `http` API. the url is whatever the flow author wrote, and
@@ -173,17 +171,36 @@ export const DECLARED_OUTBOUND_CALLS: Record<string, OutboundCallDeclaration> =
173
171
  category: 'rnx_cloud_box',
174
172
  count: 1,
175
173
  },
174
+ // a micro box's own Browser Run session, over the worker's BROWSER binding.
175
+ // the binding routes on path alone and ignores the host, so `browser.invalid`
176
+ // is a placeholder that exists only so URL can parse the search parameters.
177
+ // nothing leaves Cloudflare and no project content is sent.
178
+ 'packages/rnx-cloud-box/src/browser-run.ts :: fetch :: sessionEndpoint(undefined, { keepAliveMs, includeTargets: true })':
179
+ { category: 'rnx_cloud_box', count: 1 },
180
+ 'packages/rnx-cloud-box/src/browser-run.ts :: fetch :: `https://browser.invalid/v1/devtools/browser/${sessionId}/json/list`':
181
+ { category: 'rnx_cloud_box', count: 1 },
182
+ // twice: closing the session, and the CDP websocket upgrade that navigates a
183
+ // target. both address the same session over the same binding.
184
+ 'packages/rnx-cloud-box/src/browser-run.ts :: fetch :: `https://browser.invalid/v1/devtools/browser/${sessionId}`':
185
+ { category: 'rnx_cloud_box', count: 2 },
176
186
  // the account's own session meter: starting, listing and heartbeating the
177
187
  // session a cloud box is billed against. no project content.
178
- "packages/rnx-cloud-box/src/client.ts :: fetch :: `${options.apiOrigin.replace(/\\/+$/, '')}/api/v1/rnx/sessions`":
188
+ "packages/rnx-cloud-box/src/client.ts :: fetch :: `${options.apiOrigin.replace(/\\/+$/, '')}/api/v1/rnx/sessions${ options.accountId ? `?accountId=${encodeURIComponent(options.accountId)}` : '' }`":
179
189
  { category: 'contrast_user_action', count: 1 },
180
190
  'packages/rnx-cloud-box/src/client.ts :: fetch :: url': {
181
191
  category: 'contrast_user_action',
182
192
  count: 1,
183
193
  },
194
+ // `rnx box connect` asks the account service which box that ID or name is
195
+ // and for the box's own token. the account is the only thing that knows, so
196
+ // this is the one call that turns a name into an authorized Box reference.
197
+ 'packages/rnx-cloud-box/src/client.ts :: fetch :: connectUrl': {
198
+ category: 'contrast_user_action',
199
+ count: 1,
200
+ },
184
201
  "packages/rnx-cloud-box/src/box-do.ts :: fetch :: `${origin}/api/v1/rnx/sessions${serviceAuthorized ? '/internal' : ''}`":
185
202
  { category: 'contrast_user_action', count: 1 },
186
- "packages/rnx-cloud-box/src/box-do.ts :: fetch :: `${origin}/api/v1/rnx/sessions/${ serviceAuthority ? 'internal/' : '' }${encodeURIComponent(sessionId)}`":
203
+ "packages/rnx-cloud-box/src/box-do.ts :: fetch :: `${origin}/api/v1/rnx/sessions/${ serviceAuthority ? 'internal/' : '' }${encodeURIComponent(sessionId)}${ accountId ? `?accountId=${encodeURIComponent(accountId)}` : '' }`":
187
204
  { category: 'contrast_user_action', count: 1 },
188
205
  'packages/rnx-cloud-box/src/box-do.ts :: fetch :: `${origin}/api/v1/rnx/sessions/internal/${encodeURIComponent(sessionId)}`':
189
206
  { category: 'contrast_user_action', count: 1 },
@@ -324,6 +341,11 @@ export const DECLARED_OUTBOUND_CALLS: Record<string, OutboundCallDeclaration> =
324
341
  category: 'same_origin_runtime',
325
342
  count: 1,
326
343
  },
344
+ // the cpu simulator iframe document's dedicated worker loads the headless
345
+ // canvaskit wasm and the font and asset manifests from the page's own
346
+ // `/deps-native/engine-assets/` directory.
347
+ 'packages/sootsim-engine/src/headless/browser-tenant-worker.ts :: fetch :: new URL(name, assetBase).href':
348
+ { category: 'same_origin_runtime', count: 1 },
327
349
  // the tenant build's built-in app chunk prefetch list and the chunk bodies
328
350
  // it names, resolved against the worker chunk's own url.
329
351
  'packages/sootsim-engine/src/render-worker/app-in-worker.tsx :: fetch :: listUrl': {
package/cli/parse-args.ts CHANGED
@@ -31,6 +31,23 @@ const GLOBAL_FLAGS: Record<
31
31
  '--tab': { type: 'string' },
32
32
  }
33
33
 
34
+ // every spelling parseRnxArgs consumes before the command name, mapped to
35
+ // whether it takes a value. a command that rejects unknown flags uses this to
36
+ // tell a genuinely unknown flag apart from a global one typed after the
37
+ // command, where nothing reads it, and to show how to pass that one: telling
38
+ // someone to write `rnx --verbose <value>` earns them a second error.
39
+ export const GLOBAL_FLAG_TAKES_VALUE: ReadonlyMap<string, boolean> = new Map(
40
+ Object.entries(GLOBAL_FLAGS).flatMap(([name, def]): [string, boolean][] => {
41
+ const takesValue = def.type !== 'boolean'
42
+ return def.short
43
+ ? [
44
+ [name, takesValue],
45
+ [def.short, takesValue],
46
+ ]
47
+ : [[name, takesValue]]
48
+ }),
49
+ )
50
+
34
51
  // top-level verbs that route into runInspect. the surface is intentionally
35
52
  // tiny — everything else lives under one of the grouping verbs:
36
53
  // - `rnx get <noun>` reads
package/cli/shell-init.ts CHANGED
@@ -30,7 +30,7 @@ export function renderRnxShellInit(shell: string): string {
30
30
  claim|close) ;;
31
31
  ios)
32
32
  for _rnx_shell_session in "$@"; do
33
- if [ "$_rnx_shell_session" = '--nano' ] || [ "$_rnx_shell_session" = '--cloud' ]; then
33
+ if [ "$_rnx_shell_session" = '--remote' ]; then
34
34
  _rnx_shell_create=1
35
35
  break
36
36
  fi
@@ -48,15 +48,15 @@ export function renderRnxShellInit(shell: string): string {
48
48
 
49
49
  if { [ -n "\${BASH_VERSION:-}" ] && [ "\${BASH_SUBSHELL:-0}" -ne 0 ]; } ||
50
50
  { [ -n "\${ZSH_VERSION:-}" ] && [ "\${ZSH_SUBSHELL:-0}" -ne 0 ]; }; then
51
- printf '%s\\n' 'rnx cloud lifecycle commands must run directly in the current shell, not in a pipeline or command substitution' >&2
51
+ printf '%s\\n' 'rnx remote simulator lifecycle commands must run directly in the current shell, not in a pipeline or command substitution' >&2
52
52
  return 1
53
53
  fi
54
54
  if ( : >&9 ) 2>/dev/null; then
55
- printf '%s\\n' 'rnx cloud shell integration requires file descriptor 9 to be unused' >&2
55
+ printf '%s\\n' 'rnx remote simulator shell integration requires file descriptor 9 to be unused' >&2
56
56
  return 1
57
57
  fi
58
58
  if ! ( export ${RNX_CLOUD_SESSION_ENV}=__rnx_shell_probe && unset ${RNX_CLOUD_SESSION_ENV} ) 2>/dev/null; then
59
- printf '%s\\n' 'rnx cloud shell integration cannot update RNX_CLOUD_SESSION in this shell' >&2
59
+ printf '%s\\n' 'rnx remote simulator shell integration cannot update RNX_CLOUD_SESSION in this shell' >&2
60
60
  return 1
61
61
  fi
62
62
 
package/cli/ws-bridge.ts CHANGED
@@ -248,6 +248,35 @@ export function bridgePortForShellBaseUrl(baseUrl: string): number | null {
248
248
  return null
249
249
  }
250
250
 
251
+ /** the bridge a `--base-url` pin implies. one rule for every command that takes
252
+ * the flag, because they used to disagree: flow refused an unserved pin while
253
+ * open kept the discovered default and then started a bridge of its own, so
254
+ * the page rendered in the pinned shell and the polling waited on another
255
+ * world's bridge. that reads as "saved sim <id> is gone" and gets retried
256
+ * rather than fixed. an explicit --port states the world outright and wins;
257
+ * otherwise the pin has to name a world something serves. */
258
+ export function resolveBridgePortForPin(pin: {
259
+ baseUrl: string
260
+ wsPort: number
261
+ explicitPort: boolean
262
+ }): { port: number; error?: undefined } | { port?: undefined; error: string } {
263
+ const served = bridgePortForShellBaseUrl(pin.baseUrl)
264
+ if (served === null) {
265
+ if (pin.explicitPort) return { port: pin.wsPort }
266
+ return {
267
+ error:
268
+ `no live rnx world serves ${pin.baseUrl} — start that shell first, ` +
269
+ 'or name its bridge with --port <port>',
270
+ }
271
+ }
272
+ if (pin.explicitPort && pin.wsPort !== served) {
273
+ return {
274
+ error: `--base-url ${pin.baseUrl} belongs to bridge port ${served}, but --port ${pin.wsPort} names another world`,
275
+ }
276
+ }
277
+ return { port: served }
278
+ }
279
+
251
280
  /** default ws bridge port for CLI commands: the fresh dev bridge when a vite
252
281
  * shell is live, else the fresh daemon, else the hardcoded default. one
253
282
  * deterministic answer regardless of how the CLI was invoked (global binary
@@ -390,76 +419,94 @@ export interface ParsedBridgeCliArgs {
390
419
  commandTimeoutMs: number
391
420
  }
392
421
 
422
+ interface BridgeFlagState {
423
+ wsPort: number
424
+ explicitPort: boolean
425
+ commandTimeoutMs: number
426
+ simId: string | undefined
427
+ simIdSource: ParsedBridgeCliArgs['simIdSource']
428
+ }
429
+
430
+ // every flag parseBridgeCliArgs consumes a value for on its own, without being
431
+ // listed in a caller's stripValueFlags. the parser iterates this table, so the
432
+ // exported name list below cannot drift from what is actually parsed. a name
433
+ // missing from that list is not a parse failure, it is a command that hunts a
434
+ // positional in raw argv and takes the flag's value instead: `maestro test
435
+ // --newflag value login.yaml` would run `value` as the flow.
436
+ const BRIDGE_VALUE_FLAGS_TABLE: readonly {
437
+ names: readonly string[]
438
+ apply: (state: BridgeFlagState, value: string | undefined) => void
439
+ }[] = [
440
+ {
441
+ names: ['--port', '-p'],
442
+ // naming the flag pins the world even when the value is missing or junk,
443
+ // so a later --base-url cannot quietly retarget the run to another shell.
444
+ apply: (state, value) => {
445
+ state.explicitPort = true
446
+ if (value !== undefined) state.wsPort = Number(value)
447
+ },
448
+ },
449
+ {
450
+ names: ['--timeout'],
451
+ apply: (state, value) => {
452
+ if (value !== undefined) state.commandTimeoutMs = Number(value)
453
+ },
454
+ },
455
+ {
456
+ // `--sim` is the canonical target flag; `--session` / `--tab` are
457
+ // documented aliases (CLAUDE.md, the rnx agent skills, and engine docs all
458
+ // say `--session <id>`). without these aliases an agent following the docs
459
+ // would have `--session ef` silently ignored and get the *currently
460
+ // pinned* sim's tree instead — wrong-app data with no error.
461
+ names: ['--sim', '--session', '--tab'],
462
+ apply: (state, value) => {
463
+ if (value === undefined) return
464
+ state.simId = value.trim() || undefined
465
+ state.simIdSource = 'flag'
466
+ },
467
+ },
468
+ ]
469
+
470
+ export const BRIDGE_VALUE_FLAGS: readonly string[] = BRIDGE_VALUE_FLAGS_TABLE.flatMap(
471
+ (flag) => [...flag.names],
472
+ )
473
+
393
474
  export function parseBridgeCliArgs(
394
475
  args: string[],
395
476
  opts: ParseBridgeCliArgsOptions = {},
396
477
  ): ParsedBridgeCliArgs {
397
478
  const flagIndices = new Set<number>()
398
- let wsPort = opts.port ?? resolveDefaultBridgePort()
399
- let explicitPort = opts.port !== undefined
400
- let commandTimeoutMs = opts.commandTimeoutMs ?? 15000
401
- let simId: string | undefined
402
- let simIdSource: ParsedBridgeCliArgs['simIdSource'] = 'none'
479
+ const state: BridgeFlagState = {
480
+ wsPort: opts.port ?? resolveDefaultBridgePort(),
481
+ explicitPort: opts.port !== undefined,
482
+ commandTimeoutMs: opts.commandTimeoutMs ?? 15000,
483
+ simId: undefined,
484
+ simIdSource: 'none',
485
+ }
403
486
 
404
487
  const stripBooleanFlags = new Set(opts.stripBooleanFlags ?? [])
405
488
  const stripValueFlags = new Set(opts.stripValueFlags ?? [])
406
489
 
407
490
  for (let i = 0; i < args.length; i++) {
408
491
  const arg = args[i]
409
- if (arg === '--port' || arg === '-p') {
492
+ // both spellings for every flag in the table: `--flag value` and
493
+ // `--flag=value`.
494
+ const valueFlag = BRIDGE_VALUE_FLAGS_TABLE.find((flag) =>
495
+ flag.names.some((name) => arg === name || arg.startsWith(`${name}=`)),
496
+ )
497
+ if (valueFlag) {
410
498
  flagIndices.add(i)
411
- explicitPort = true
412
- if (i + 1 < args.length) {
413
- flagIndices.add(i + 1)
414
- wsPort = Number(args[i + 1])
499
+ const inline = valueFlag.names.find((name) => arg.startsWith(`${name}=`))
500
+ if (inline) {
501
+ valueFlag.apply(state, arg.slice(inline.length + 1))
502
+ continue
415
503
  }
504
+ const value = i + 1 < args.length ? args[i + 1] : undefined
505
+ if (value !== undefined) flagIndices.add(i + 1)
506
+ valueFlag.apply(state, value)
416
507
  i++
417
508
  continue
418
509
  }
419
- if (arg.startsWith('--port=')) {
420
- flagIndices.add(i)
421
- explicitPort = true
422
- wsPort = Number(arg.slice('--port='.length))
423
- continue
424
- }
425
- if (arg === '--timeout') {
426
- flagIndices.add(i)
427
- if (i + 1 < args.length) {
428
- flagIndices.add(i + 1)
429
- commandTimeoutMs = Number(args[i + 1])
430
- }
431
- i++
432
- continue
433
- }
434
- // `--sim` is the canonical target flag; `--session` / `--tab` are
435
- // documented aliases (CLAUDE.md, the rnx agent skills, and engine docs all
436
- // say `--session <id>`). without these aliases an agent following the docs
437
- // would have `--session ef` silently ignored and get the *currently
438
- // pinned* sim's tree instead — wrong-app data with no error. accept the
439
- // `--flag value` and `--flag=value` forms for all three spellings.
440
- if (arg === '--sim' || arg === '--session' || arg === '--tab') {
441
- flagIndices.add(i)
442
- if (i + 1 < args.length) {
443
- flagIndices.add(i + 1)
444
- simId = args[i + 1]?.trim() || undefined
445
- simIdSource = 'flag'
446
- }
447
- i++
448
- continue
449
- }
450
- const simEq = arg.startsWith('--sim=')
451
- ? arg.slice('--sim='.length)
452
- : arg.startsWith('--session=')
453
- ? arg.slice('--session='.length)
454
- : arg.startsWith('--tab=')
455
- ? arg.slice('--tab='.length)
456
- : undefined
457
- if (simEq !== undefined) {
458
- flagIndices.add(i)
459
- simId = simEq.trim() || undefined
460
- simIdSource = 'flag'
461
- continue
462
- }
463
510
  if (stripBooleanFlags.has(arg)) {
464
511
  flagIndices.add(i)
465
512
  continue
@@ -473,21 +520,21 @@ export function parseBridgeCliArgs(
473
520
  }
474
521
  }
475
522
 
476
- if (!simId) {
523
+ if (!state.simId) {
477
524
  const savedSim = readCurrentSim()
478
525
  if (savedSim) {
479
- simId = savedSim.simId.trim() || undefined
480
- simIdSource = 'saved'
526
+ state.simId = savedSim.simId.trim() || undefined
527
+ state.simIdSource = 'saved'
481
528
  }
482
529
  }
483
530
 
484
531
  return {
485
532
  positional: args.filter((_, i) => !flagIndices.has(i)),
486
- wsPort,
487
- explicitPort,
488
- simId,
489
- simIdSource,
490
- commandTimeoutMs,
533
+ wsPort: state.wsPort,
534
+ explicitPort: state.explicitPort,
535
+ simId: state.simId,
536
+ simIdSource: state.simIdSource,
537
+ commandTimeoutMs: state.commandTimeoutMs,
491
538
  }
492
539
  }
493
540
 
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (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.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (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.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (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.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (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.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (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.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (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;
@@ -36,6 +36,7 @@ __export(shared_session_exports, {
36
36
  getSharedDesktopAuthFilePath: () => getSharedDesktopAuthFilePath,
37
37
  readSharedDesktopAuthSession: () => readSharedDesktopAuthSession,
38
38
  refreshSharedDesktopAuthSession: () => refreshSharedDesktopAuthSession,
39
+ sharedDesktopAuthAccounts: () => sharedDesktopAuthAccounts,
39
40
  writeSharedDesktopAuthSession: () => writeSharedDesktopAuthSession
40
41
  });
41
42
  module.exports = __toCommonJS(shared_session_exports);
@@ -60,6 +61,12 @@ function electronUserDataDir() {
60
61
  var DAEMON_LOCKFILE_MAX_BYTES = 16 * 1024;
61
62
 
62
63
  // src/auth/shared-session.ts
64
+ function sharedDesktopAuthAccounts(user) {
65
+ return [
66
+ ...user?.personalAccountId ? [{ id: user.personalAccountId, name: "Personal" }] : [],
67
+ ...(user?.teams ?? []).map((team) => ({ id: team.id, name: team.name }))
68
+ ];
69
+ }
63
70
  var SESSION_VERSION = 1;
64
71
  var SESSION_FILE_ENV = "SOOTSIM_SHARED_AUTH_FILE";
65
72
  var DEFAULT_ORIGIN = "https://contrast.dev";
@@ -85,6 +92,7 @@ function normalizeUser(input) {
85
92
  email: typeof value.email === "string" ? value.email : void 0,
86
93
  image: typeof value.image === "string" ? value.image : void 0,
87
94
  githubUsername: typeof value.githubUsername === "string" ? value.githubUsername : void 0,
95
+ personalAccountId: typeof value.personalAccountId === "string" && value.personalAccountId.trim() ? value.personalAccountId.trim() : void 0,
88
96
  isAdmin: value.isAdmin === true,
89
97
  teams: Array.isArray(value.teams) ? value.teams.map((team) => {
90
98
  if (!team || typeof team !== "object") return null;
@@ -108,6 +116,7 @@ function normalizeSession(input) {
108
116
  const source = value.source === "cli" || value.source === "electron" || value.source === "browser" || value.source === "unknown" ? value.source : "unknown";
109
117
  const updatedAt = typeof value.updatedAt === "string" && value.updatedAt ? value.updatedAt : (/* @__PURE__ */ new Date()).toISOString();
110
118
  const validatedAt = typeof value.validatedAt === "string" && value.validatedAt ? value.validatedAt : void 0;
119
+ const accountId = typeof value.accountId === "string" && value.accountId.trim() ? value.accountId.trim() : void 0;
111
120
  return {
112
121
  version: SESSION_VERSION,
113
122
  token: value.token.trim(),
@@ -115,7 +124,8 @@ function normalizeSession(input) {
115
124
  origin,
116
125
  source,
117
126
  updatedAt,
118
- validatedAt
127
+ validatedAt,
128
+ accountId
119
129
  };
120
130
  }
121
131
  function readSharedDesktopAuthSession() {
@@ -144,7 +154,8 @@ function writeSharedDesktopAuthSession(session) {
144
154
  origin: session.origin?.trim() || DEFAULT_ORIGIN,
145
155
  source: session.source,
146
156
  updatedAt: session.updatedAt || (/* @__PURE__ */ new Date()).toISOString(),
147
- validatedAt: session.validatedAt
157
+ validatedAt: session.validatedAt,
158
+ accountId: session.accountId?.trim() || void 0
148
159
  };
149
160
  (0, import_node_fs.writeFileSync)(filepath, JSON.stringify(normalized, null, 2) + "\n");
150
161
  try {
@@ -179,7 +190,8 @@ async function refreshSharedDesktopAuthSession(originOverride) {
179
190
  user: data.user,
180
191
  origin,
181
192
  source: current.source,
182
- validatedAt: (/* @__PURE__ */ new Date()).toISOString()
193
+ validatedAt: (/* @__PURE__ */ new Date()).toISOString(),
194
+ accountId: current.accountId
183
195
  });
184
196
  } catch {
185
197
  return current;
@@ -191,5 +203,6 @@ async function refreshSharedDesktopAuthSession(originOverride) {
191
203
  getSharedDesktopAuthFilePath,
192
204
  readSharedDesktopAuthSession,
193
205
  refreshSharedDesktopAuthSession,
206
+ sharedDesktopAuthAccounts,
194
207
  writeSharedDesktopAuthSession
195
208
  });
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (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.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (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.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/beta.ts
4
4
  var IS_BETA = true;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (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.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (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.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var SIM_LONG_PRESS_MAX_MS = 5e3;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (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.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var SIM_LONG_PRESS_DEFAULT_MS = 500;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (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.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/capture-contract.ts
4
4
  var RNX_SCREEN_CAPTURE_VERSION = 1;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (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.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (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.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/cloud-contract.ts
4
4
  var RNX_CLOUD_MAX_ARTIFACT_BYTES = 20 * 1024 * 1024;