peachsim 0.1.1406 → 0.1.1465
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +8 -4
- package/README.md +22 -2
- package/cli/app-fonts.ts +50 -44
- package/cli/bin.ts +5 -4
- package/cli/bridge-diagnostics.ts +5 -0
- package/cli/bridge-flow-runner.ts +21 -13
- package/cli/cloud-client.ts +4 -3
- package/cli/commands/control.ts +155 -123
- package/cli/commands/daemon-mac-app.ts +3 -3
- package/cli/commands/daemon.ts +2 -2
- package/cli/commands/do-chain.ts +9 -2
- package/cli/commands/electron.ts +4 -1
- package/cli/commands/inspect/core.ts +1 -1
- package/cli/commands/inspect/settle.ts +19 -7
- package/cli/commands/inspect/settling.ts +92 -56
- package/cli/commands/inspect/wait-idle.ts +21 -9
- package/cli/commands/inspect/wait-ready.ts +22 -8
- package/cli/commands/inspect.ts +101 -134
- package/cli/commands/setup.ts +26 -16
- package/cli/commands/upgrade.ts +53 -9
- package/cli/desktop-companion.ts +1 -1
- package/cli/drivers/playwright-sim-host.ts +32 -13
- package/cli/drivers/playwright.ts +3 -3
- package/cli/main.ts +14 -5
- package/cli/outbound-endpoints.ts +1 -9
- package/detox/index.ts +6 -1
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract-input.cjs +1 -1
- package/dist-lib/bridge-contract-input.mjs +1 -1
- package/dist-lib/bridge-contract.cjs +3 -3
- package/dist-lib/bridge-contract.mjs +3 -3
- package/dist-lib/bundle-channel.cjs +322 -274
- package/dist-lib/capture-contract.cjs +1 -1
- package/dist-lib/capture-contract.mjs +1 -1
- package/dist-lib/cloud-contract.cjs +1 -1
- package/dist-lib/cloud-contract.mjs +1 -1
- package/dist-lib/cloud-test-args.cjs +1 -1
- package/dist-lib/cloud-test-args.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/config.mjs +1 -1
- package/dist-lib/detox/index.cjs +512 -122
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/expo-swift-bundle.cjs +69 -33
- package/dist-lib/expo-swift-metadata.cjs +1 -1
- package/dist-lib/expo-swift-metadata.mjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +3650 -3528
- 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 +327 -123
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/kotlin-host.cjs +10 -5
- 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 +49 -47
- package/dist-lib/native-app-identity-project.cjs +1 -1
- package/dist-lib/native-app-identity-project.mjs +1 -1
- package/dist-lib/native-app-identity.cjs +1 -1
- package/dist-lib/native-app-identity.mjs +1 -1
- package/dist-lib/native-firebase-metadata.cjs +1 -1
- package/dist-lib/native-firebase-metadata.mjs +1 -1
- package/dist-lib/plist.cjs +1 -1
- package/dist-lib/plist.mjs +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/scripts/dev-server-scanner.cjs +23 -17
- package/dist-lib/sdk.cjs +99 -61
- package/dist-lib/sdk.mjs +97 -61
- package/dist-lib/skills.cjs +3347 -3051
- package/dist-lib/swift-compile.cjs +26 -12
- package/dist-lib/swift-compile.mjs +26 -12
- package/dist-lib/swift-package.cjs +1 -1
- package/dist-lib/swift-package.mjs +1 -1
- package/dist-lib/swift-submit.cjs +2 -2
- package/dist-lib/swift-submit.mjs +2 -2
- package/dist-lib/swift-toolchain.cjs +1 -1
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite-swift.cjs +66 -31
- package/dist-lib/vite.cjs +1 -1
- package/dist-lib/worklet-executable.cjs +5 -1
- package/dist-lib/worklet-executable.mjs +5 -1
- package/kotlin/AppSources/android/view/Window.kt +2 -0
- package/kotlin/AppSources/dev/peach/app/PeachApp.kt +1 -1
- package/kotlin/ComposeSources/PeachComposeHost.kt +35 -9
- package/kotlin/ExpoComposeSources/dev/peach/expo/PeachExpoCompose.kt +2 -2
- package/kotlin/ExpoSources/dev/peach/expo/PeachExpoRuntime.kt +9 -6
- package/kotlin/ExpoSources/dev/peach/expo/PeachExpoTypes.kt +4 -4
- package/kotlin/ExpoSources/expo/modules/kotlin/modules/Module.kt +2 -2
- package/kotlin/ExpoSources/expo/modules/kotlin/viewevent/ViewEvent.kt +22 -8
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ExpoView.kt +0 -3
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewDefinitionBuilder.kt +10 -9
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewProps.kt +6 -5
- package/kotlin/fixtures/import-drawing/Drawing.d.kt.ts +7 -0
- package/kotlin/fixtures/import-drawing/Drawing.kt +101 -0
- package/kotlin/fixtures/import-drawing/ImportDrawing.native.tsx +18 -0
- package/kotlin/fixtures/import-drawing/README.md +34 -0
- package/kotlin/fixtures/import-drawing/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-drawing/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-drawing/package.json +23 -0
- package/kotlin/fixtures/import-drawing/tsconfig.json +20 -0
- package/kotlin/fixtures/import-drawing/vite.config.ts +20 -0
- package/kotlin/fixtures/import-scroll/ImportNested.native.tsx +10 -0
- package/kotlin/fixtures/import-scroll/Nested.d.kt.ts +4 -0
- package/kotlin/fixtures/import-scroll/README.md +15 -0
- package/kotlin/fixtures/import-scroll/app/nested+spa.tsx +1 -0
- package/kotlin/fixtures/import-values/ImportValues.native.tsx +26 -0
- package/kotlin/fixtures/import-values/README.md +6 -1
- package/kotlin/fixtures/import-values/Values.d.kt.ts +4 -0
- package/kotlin/fixtures/import-values/Values.kt +18 -0
- package/kotlin/tools/expo-types.main.kts +17 -5
- package/package.json +2 -1
- package/scripts/dev-server-scanner.ts +33 -23
- package/src/assetCatalogContract.ts +7 -0
- package/src/bridge-contract.ts +21 -3
- package/src/connect.ts +18 -5
- package/src/desktop-host-delivery.ts +33 -3
- package/src/expo-swift-host.ts +6 -3
- package/src/host/bridge-host.ts +2 -0
- package/src/host/fetch-proxy-transport.ts +8 -0
- package/src/kotlin-host.ts +11 -5
- package/src/native-firebase-config.ts +95 -54
- package/src/process-output.ts +16 -0
- package/src/sdk.ts +6 -1
- package/src/sim-client.ts +6 -1
- package/src/swift-compile.ts +36 -15
- package/src/swift-distribution.lock.json +8 -8
- package/src/swift-standin-emit.ts +10 -1
- package/src/swift-standins.ts +21 -7
- package/src/swift-submit.ts +6 -1
- package/src/worklet-executable.ts +7 -2
- /package/kotlin/fixtures/{kotlin-app-variants → import-scroll}/Nested.kt +0 -0
package/cli/commands/inspect.ts
CHANGED
|
@@ -84,7 +84,7 @@ import {
|
|
|
84
84
|
} from './inspect/resolve-target'
|
|
85
85
|
import { runScreensSubcommand } from './inspect/screens'
|
|
86
86
|
import { runSettleSubcommand } from './inspect/settle'
|
|
87
|
-
import { waitForSootsimIdle } from './inspect/settling'
|
|
87
|
+
import { IdleObservationError, waitForSootsimIdle } from './inspect/settling'
|
|
88
88
|
import {
|
|
89
89
|
callShellCommand,
|
|
90
90
|
callShellCommandWhenReady,
|
|
@@ -1369,8 +1369,14 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
1369
1369
|
` ⚠ auto-wait timed out after ${elapsed ?? budgetMs}ms (${blockedBy}) — next command may see mid-animation state. use \`peach do settle\` for a longer wait.\n`,
|
|
1370
1370
|
)
|
|
1371
1371
|
}
|
|
1372
|
-
} catch {
|
|
1373
|
-
//
|
|
1372
|
+
} catch (error) {
|
|
1373
|
+
// the write already landed. an unread idle probe must not fail it or
|
|
1374
|
+
// claim the screen was watched until the budget.
|
|
1375
|
+
if (error instanceof IdleObservationError) {
|
|
1376
|
+
process.stderr.write(
|
|
1377
|
+
` ⚠ ${error.message}. next command may see mid-animation state. use \`peach do settle\` to retry.\n`,
|
|
1378
|
+
)
|
|
1379
|
+
}
|
|
1374
1380
|
}
|
|
1375
1381
|
}
|
|
1376
1382
|
|
|
@@ -1721,7 +1727,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
1721
1727
|
break
|
|
1722
1728
|
}
|
|
1723
1729
|
if (args.includes('--json')) {
|
|
1724
|
-
|
|
1730
|
+
printJson(nodes)
|
|
1725
1731
|
} else {
|
|
1726
1732
|
console.log(` accessibility tree (${nodes.length} nodes):\n`)
|
|
1727
1733
|
for (const n of nodes) {
|
|
@@ -1845,19 +1851,15 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
1845
1851
|
}
|
|
1846
1852
|
const absolute = Reflect.get(node, 'absolutePosition')
|
|
1847
1853
|
const size = Reflect.get(node, 'layout')
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
: null,
|
|
1858
|
-
null,
|
|
1859
|
-
2,
|
|
1860
|
-
),
|
|
1854
|
+
printJson(
|
|
1855
|
+
absolute && size
|
|
1856
|
+
? {
|
|
1857
|
+
x: Reflect.get(absolute, 'x'),
|
|
1858
|
+
y: Reflect.get(absolute, 'y'),
|
|
1859
|
+
width: Reflect.get(size, 'width'),
|
|
1860
|
+
height: Reflect.get(size, 'height'),
|
|
1861
|
+
}
|
|
1862
|
+
: null,
|
|
1861
1863
|
)
|
|
1862
1864
|
break
|
|
1863
1865
|
}
|
|
@@ -1899,7 +1901,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
1899
1901
|
code: buildSampleColorEval(rect),
|
|
1900
1902
|
})
|
|
1901
1903
|
if (args.includes('--json')) {
|
|
1902
|
-
|
|
1904
|
+
printJson(result)
|
|
1903
1905
|
} else {
|
|
1904
1906
|
const { r, g, b, a, hex, samples } = result as {
|
|
1905
1907
|
r: number
|
|
@@ -1933,19 +1935,15 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
1933
1935
|
? null
|
|
1934
1936
|
: await inspectFind(bridge, { text: matcher })
|
|
1935
1937
|
const node = byTestId?.result ?? byText?.result ?? null
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
: { matcher, found: false },
|
|
1946
|
-
null,
|
|
1947
|
-
2,
|
|
1948
|
-
),
|
|
1938
|
+
printJson(
|
|
1939
|
+
node
|
|
1940
|
+
? {
|
|
1941
|
+
matcher,
|
|
1942
|
+
found: true,
|
|
1943
|
+
resolvedVia: byTestId?.result ? 'testID' : 'text',
|
|
1944
|
+
node,
|
|
1945
|
+
}
|
|
1946
|
+
: { matcher, found: false },
|
|
1949
1947
|
)
|
|
1950
1948
|
break
|
|
1951
1949
|
}
|
|
@@ -1956,7 +1954,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
1956
1954
|
type: 'evaluate',
|
|
1957
1955
|
code: buildGetNodeEval(matcher),
|
|
1958
1956
|
})
|
|
1959
|
-
|
|
1957
|
+
printJson(result)
|
|
1960
1958
|
break
|
|
1961
1959
|
}
|
|
1962
1960
|
|
|
@@ -2013,16 +2011,10 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
2013
2011
|
if (candidate) {
|
|
2014
2012
|
await recordInspectAction('inspect tap', candidate.step, candidate.summary)
|
|
2015
2013
|
}
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
...outcome.result,
|
|
2021
|
-
},
|
|
2022
|
-
null,
|
|
2023
|
-
2,
|
|
2024
|
-
),
|
|
2025
|
-
)
|
|
2014
|
+
printJson({
|
|
2015
|
+
...(outcome.attempts > 1 ? { attempts: outcome.attempts } : {}),
|
|
2016
|
+
...outcome.result,
|
|
2017
|
+
})
|
|
2026
2018
|
break
|
|
2027
2019
|
}
|
|
2028
2020
|
if (!Number.isFinite(x) || !Number.isFinite(y)) {
|
|
@@ -2036,7 +2028,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
2036
2028
|
if (candidate) {
|
|
2037
2029
|
await recordInspectAction('inspect tap', candidate.step, candidate.summary)
|
|
2038
2030
|
}
|
|
2039
|
-
|
|
2031
|
+
printJson(result)
|
|
2040
2032
|
break
|
|
2041
2033
|
}
|
|
2042
2034
|
|
|
@@ -2087,7 +2079,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
2087
2079
|
`${subcommand} ${fromX},${fromY} -> ${toX},${toY}`,
|
|
2088
2080
|
)
|
|
2089
2081
|
}
|
|
2090
|
-
|
|
2082
|
+
printJson(result)
|
|
2091
2083
|
break
|
|
2092
2084
|
}
|
|
2093
2085
|
|
|
@@ -2149,7 +2141,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
2149
2141
|
`pinch (${fromX1},${fromY1}) (${fromX2},${fromY2}) -> (${toX1},${toY1}) (${toX2},${toY2})`,
|
|
2150
2142
|
)
|
|
2151
2143
|
}
|
|
2152
|
-
|
|
2144
|
+
printJson(result)
|
|
2153
2145
|
break
|
|
2154
2146
|
}
|
|
2155
2147
|
|
|
@@ -2302,33 +2294,27 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
2302
2294
|
'text',
|
|
2303
2295
|
)
|
|
2304
2296
|
await recordInspectAction('inspect tap-text', candidate.step, candidate.summary)
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
result: outcome.result,
|
|
2327
|
-
},
|
|
2328
|
-
null,
|
|
2329
|
-
2,
|
|
2330
|
-
),
|
|
2331
|
-
)
|
|
2297
|
+
printJson({
|
|
2298
|
+
matched: payload.match,
|
|
2299
|
+
tapped: {
|
|
2300
|
+
nodeId: payload.target?.nodeId ?? null,
|
|
2301
|
+
id: payload.target?.id ?? null,
|
|
2302
|
+
testID: payload.target?.testID ?? null,
|
|
2303
|
+
type: payload.target?.type ?? null,
|
|
2304
|
+
cx: payload.cx,
|
|
2305
|
+
cy: payload.cy,
|
|
2306
|
+
},
|
|
2307
|
+
...(payload.strategy && payload.strategy !== 'matched-node'
|
|
2308
|
+
? { strategy: payload.strategy }
|
|
2309
|
+
: {}),
|
|
2310
|
+
// expose the disambiguation outcome so agents can confirm which
|
|
2311
|
+
// of the N matches was tapped, or notice that only one exists.
|
|
2312
|
+
...(payload.total > 1 || nthIndex !== null
|
|
2313
|
+
? { nth: { index: payload.idx, total: payload.total } }
|
|
2314
|
+
: {}),
|
|
2315
|
+
...(outcome.attempts > 1 ? { attempts: outcome.attempts } : {}),
|
|
2316
|
+
result: outcome.result,
|
|
2317
|
+
})
|
|
2332
2318
|
break
|
|
2333
2319
|
}
|
|
2334
2320
|
|
|
@@ -2400,25 +2386,19 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
2400
2386
|
payload.strategy === 'testid' ? 'id' : 'text',
|
|
2401
2387
|
)
|
|
2402
2388
|
await recordInspectAction('inspect tap-best', candidate.step, candidate.summary)
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
result: outcome.result,
|
|
2417
|
-
},
|
|
2418
|
-
null,
|
|
2419
|
-
2,
|
|
2420
|
-
),
|
|
2421
|
-
)
|
|
2389
|
+
printJson({
|
|
2390
|
+
matched: {
|
|
2391
|
+
strategy: payload.strategy,
|
|
2392
|
+
nodeId: node.nodeId,
|
|
2393
|
+
id: node.id,
|
|
2394
|
+
testID: node.testID,
|
|
2395
|
+
type: node.type,
|
|
2396
|
+
text: node.text,
|
|
2397
|
+
},
|
|
2398
|
+
tapped: { cx: payload.cx, cy: payload.cy },
|
|
2399
|
+
...(outcome.attempts > 1 ? { attempts: outcome.attempts } : {}),
|
|
2400
|
+
result: outcome.result,
|
|
2401
|
+
})
|
|
2422
2402
|
break
|
|
2423
2403
|
}
|
|
2424
2404
|
|
|
@@ -2577,20 +2557,14 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
2577
2557
|
? `type-into #${targetId} ${SECURE_TEXT_REDACTION}`
|
|
2578
2558
|
: `type-into #${targetId} ${JSON.stringify(text)}`,
|
|
2579
2559
|
)
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
typed: outputText,
|
|
2589
|
-
},
|
|
2590
|
-
null,
|
|
2591
|
-
2,
|
|
2592
|
-
),
|
|
2593
|
-
)
|
|
2560
|
+
printJson({
|
|
2561
|
+
target: targetId,
|
|
2562
|
+
isTextInput: tiPayload.isTextInput,
|
|
2563
|
+
secureTextEntry,
|
|
2564
|
+
keyboardOpened: keyboardState.visible ?? tapResult?.keyboardOpened ?? false,
|
|
2565
|
+
focusedInput,
|
|
2566
|
+
typed: outputText,
|
|
2567
|
+
})
|
|
2594
2568
|
break
|
|
2595
2569
|
}
|
|
2596
2570
|
|
|
@@ -2770,7 +2744,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
2770
2744
|
`double-tap @${x},${y}`,
|
|
2771
2745
|
)
|
|
2772
2746
|
}
|
|
2773
|
-
|
|
2747
|
+
printJson(result)
|
|
2774
2748
|
break
|
|
2775
2749
|
}
|
|
2776
2750
|
|
|
@@ -2828,7 +2802,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
2828
2802
|
`long-press @${x},${y}`,
|
|
2829
2803
|
)
|
|
2830
2804
|
}
|
|
2831
|
-
|
|
2805
|
+
printJson(result)
|
|
2832
2806
|
break
|
|
2833
2807
|
}
|
|
2834
2808
|
|
|
@@ -2955,13 +2929,12 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
2955
2929
|
`gesture ${preset}`,
|
|
2956
2930
|
)
|
|
2957
2931
|
}
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
)
|
|
2932
|
+
printJson({
|
|
2933
|
+
preset,
|
|
2934
|
+
from: { x: fromX, y: fromY },
|
|
2935
|
+
to: { x: toX, y: toY },
|
|
2936
|
+
result,
|
|
2937
|
+
})
|
|
2965
2938
|
break
|
|
2966
2939
|
}
|
|
2967
2940
|
|
|
@@ -2996,16 +2969,10 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
2996
2969
|
`scroll #${id} -> ${x},${y}`,
|
|
2997
2970
|
)
|
|
2998
2971
|
}
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
...(scrollNode ? { at: { x: scrollNode.cx, y: scrollNode.cy } } : {}),
|
|
3004
|
-
},
|
|
3005
|
-
null,
|
|
3006
|
-
2,
|
|
3007
|
-
),
|
|
3008
|
-
)
|
|
2972
|
+
printJson({
|
|
2973
|
+
...result,
|
|
2974
|
+
...(scrollNode ? { at: { x: scrollNode.cx, y: scrollNode.cy } } : {}),
|
|
2975
|
+
})
|
|
3009
2976
|
break
|
|
3010
2977
|
}
|
|
3011
2978
|
|
|
@@ -3032,7 +2999,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
3032
2999
|
if (shell) base.shell = shell
|
|
3033
3000
|
} catch {}
|
|
3034
3001
|
}
|
|
3035
|
-
|
|
3002
|
+
printJson(base)
|
|
3036
3003
|
break
|
|
3037
3004
|
}
|
|
3038
3005
|
if (!stateCmd || stateCmd === '--help' || stateCmd === '-h') {
|
|
@@ -3225,7 +3192,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
3225
3192
|
console.error(` unknown state subcommand: ${stateCmd}`)
|
|
3226
3193
|
peachExit(1)
|
|
3227
3194
|
}
|
|
3228
|
-
|
|
3195
|
+
printJson(result)
|
|
3229
3196
|
break
|
|
3230
3197
|
}
|
|
3231
3198
|
|
|
@@ -3410,7 +3377,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
3410
3377
|
console.error(` unknown shell subcommand: ${shellCmd}`)
|
|
3411
3378
|
peachExit(1)
|
|
3412
3379
|
}
|
|
3413
|
-
|
|
3380
|
+
printJson({ ok, settled, state })
|
|
3414
3381
|
break
|
|
3415
3382
|
}
|
|
3416
3383
|
|
|
@@ -3686,7 +3653,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
3686
3653
|
type: 'evaluate',
|
|
3687
3654
|
code: `(async () => SootSim.bridges.test.evalInTenant(${JSON.stringify(tenantCode)}))()`,
|
|
3688
3655
|
})
|
|
3689
|
-
|
|
3656
|
+
printJson(result)
|
|
3690
3657
|
break
|
|
3691
3658
|
}
|
|
3692
3659
|
// wrap in async to support await in worker mode. no identifier
|
|
@@ -3701,7 +3668,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
3701
3668
|
: `(async () => ${expandedCode})()`
|
|
3702
3669
|
}
|
|
3703
3670
|
const result = await bridge.send({ type: 'evaluate', code: expandedCode })
|
|
3704
|
-
|
|
3671
|
+
printJson(result)
|
|
3705
3672
|
|
|
3706
3673
|
// suggest CLI commands for common verbose eval patterns
|
|
3707
3674
|
const lc = code.toLowerCase()
|
|
@@ -4124,7 +4091,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
4124
4091
|
(await callTestBridge<Array<Record<string, any>>>(bridge, 'listAnimations')) ??
|
|
4125
4092
|
[]
|
|
4126
4093
|
if (args.includes('--json')) {
|
|
4127
|
-
|
|
4094
|
+
printJson(anims)
|
|
4128
4095
|
break
|
|
4129
4096
|
}
|
|
4130
4097
|
if (anims.length === 0) {
|
|
@@ -4171,7 +4138,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
4171
4138
|
peachExit(1)
|
|
4172
4139
|
}
|
|
4173
4140
|
const result = await callTestBridge(bridge, 'getAnimation', id)
|
|
4174
|
-
|
|
4141
|
+
printJson(result)
|
|
4175
4142
|
break
|
|
4176
4143
|
}
|
|
4177
4144
|
|
|
@@ -4302,7 +4269,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
4302
4269
|
peachExit(1)
|
|
4303
4270
|
}
|
|
4304
4271
|
if (jsonOut) {
|
|
4305
|
-
|
|
4272
|
+
printJson(entry)
|
|
4306
4273
|
} else {
|
|
4307
4274
|
printNetworkDetail(entry)
|
|
4308
4275
|
}
|
|
@@ -4365,7 +4332,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
4365
4332
|
const all = await fetchEntries()
|
|
4366
4333
|
const filtered = applyFilter(all).slice(-limit)
|
|
4367
4334
|
if (jsonOut) {
|
|
4368
|
-
|
|
4335
|
+
printJson(filtered)
|
|
4369
4336
|
break
|
|
4370
4337
|
}
|
|
4371
4338
|
if (filtered.length === 0) {
|
|
@@ -4506,7 +4473,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
4506
4473
|
const all = await fetchEntries()
|
|
4507
4474
|
const filtered = applyFilter(all).slice(-limit)
|
|
4508
4475
|
if (jsonOut) {
|
|
4509
|
-
|
|
4476
|
+
printJson(filtered)
|
|
4510
4477
|
break
|
|
4511
4478
|
}
|
|
4512
4479
|
if (filtered.length === 0) {
|
package/cli/commands/setup.ts
CHANGED
|
@@ -6,7 +6,7 @@ import os from 'node:os'
|
|
|
6
6
|
import path from 'node:path'
|
|
7
7
|
import { DEFAULT_SOOTSIM_BRIDGE_PORT } from '../../src/bridge-constants'
|
|
8
8
|
import { getCliVersion } from '../../src/cli-version'
|
|
9
|
-
import { desktopHostPlatform } from '../../src/desktop-host-delivery'
|
|
9
|
+
import { desktopHostDelivery, desktopHostPlatform } from '../../src/desktop-host-delivery'
|
|
10
10
|
import {
|
|
11
11
|
readActiveRuntime,
|
|
12
12
|
readPrivacyPreferences,
|
|
@@ -129,6 +129,13 @@ export async function runSetup(
|
|
|
129
129
|
? await install()
|
|
130
130
|
: await withSpinner(`Preparing runtime ${runtimeVersion}`, install)
|
|
131
131
|
runtimeInstalled = result.installed
|
|
132
|
+
// headless runs on linux attach the standalone host; fetching it here keeps
|
|
133
|
+
// the download out of the first `peach open`
|
|
134
|
+
if (desktopHostPlatform() === 'linux-x64') {
|
|
135
|
+
const host = () => desktopHostDelivery().install({ quiet: !options.json })
|
|
136
|
+
if (options.json) await host()
|
|
137
|
+
else await withSpinner('Preparing the native host', host)
|
|
138
|
+
}
|
|
132
139
|
}
|
|
133
140
|
|
|
134
141
|
let serviceInstalled = serviceStatus.installed
|
|
@@ -150,6 +157,7 @@ export async function runSetup(
|
|
|
150
157
|
|
|
151
158
|
if (
|
|
152
159
|
simulatorDriver !== 'playwright' &&
|
|
160
|
+
process.platform !== 'darwin' &&
|
|
153
161
|
!options.dryRun &&
|
|
154
162
|
(simulatorDriver === 'desktop' || !findDesktopCompanion({ native: false }))
|
|
155
163
|
) {
|
|
@@ -315,27 +323,29 @@ async function decideService(
|
|
|
315
323
|
async function decideSimulatorDriver(
|
|
316
324
|
options: SetupOptions,
|
|
317
325
|
): Promise<SimulatorDriverPreference> {
|
|
326
|
+
if (process.platform === 'darwin' && !findDesktopCompanion()) {
|
|
327
|
+
if (options.simulatorDriver && options.simulatorDriver !== 'playwright') {
|
|
328
|
+
throw new Error('install the Mac app with `peach desktop install --native` first')
|
|
329
|
+
}
|
|
330
|
+
return 'playwright'
|
|
331
|
+
}
|
|
318
332
|
if (options.simulatorDriver) return options.simulatorDriver
|
|
319
333
|
const current = readSimulatorDriverPreference()
|
|
320
334
|
if (current) return current
|
|
321
335
|
if (options.ci || options.yes || options.dryRun) return 'playwright'
|
|
322
336
|
requireInteractive(options, '--desktop or --browser')
|
|
323
337
|
const desktopDescription =
|
|
324
|
-
|
|
325
|
-
? 'Desktop
|
|
326
|
-
: process.platform === '
|
|
327
|
-
? 'Desktop downloads
|
|
328
|
-
:
|
|
329
|
-
? 'Desktop downloads and runs the peach installer.'
|
|
330
|
-
: 'Desktop downloads the matching peach AppImage.'
|
|
338
|
+
process.platform === 'darwin'
|
|
339
|
+
? 'Desktop opens your installed native app.'
|
|
340
|
+
: process.platform === 'win32'
|
|
341
|
+
? 'Desktop downloads and runs the peach installer.'
|
|
342
|
+
: 'Desktop downloads the matching peach AppImage.'
|
|
331
343
|
const desktopChoice =
|
|
332
|
-
|
|
333
|
-
? 'Desktop app
|
|
334
|
-
: process.platform === '
|
|
335
|
-
? 'Desktop app
|
|
336
|
-
:
|
|
337
|
-
? 'Desktop app Runs the peach installer'
|
|
338
|
-
: 'Desktop app Installs the matching AppImage'
|
|
344
|
+
process.platform === 'darwin'
|
|
345
|
+
? 'Desktop app Opens your installed native host'
|
|
346
|
+
: process.platform === 'win32'
|
|
347
|
+
? 'Desktop app Runs the peach installer'
|
|
348
|
+
: 'Desktop app Installs the matching AppImage'
|
|
339
349
|
printPromptBlock('Simulator window', [
|
|
340
350
|
'Browser opens immediately in an isolated Chrome window.',
|
|
341
351
|
desktopDescription,
|
|
@@ -347,7 +357,7 @@ async function decideSimulatorDriver(
|
|
|
347
357
|
])
|
|
348
358
|
return choice === 0
|
|
349
359
|
? 'playwright'
|
|
350
|
-
:
|
|
360
|
+
: process.platform === 'darwin'
|
|
351
361
|
? 'desktop'
|
|
352
362
|
: 'electron'
|
|
353
363
|
}
|
package/cli/commands/upgrade.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
// peach upgrade updates the separately delivered runtime
|
|
2
|
-
//
|
|
3
|
-
// the running cli's files
|
|
1
|
+
// peach upgrade updates the separately delivered runtime (and on linux the native
|
|
2
|
+
// host headless runs attach) first, then atomically replaces the standalone cli
|
|
3
|
+
// executable. runtime stays first because replacing the running cli's files
|
|
4
|
+
// before later dynamic imports can strand the command.
|
|
5
|
+
// once both are in place, a running background daemon is restarted by the new
|
|
6
|
+
// executable, so nobody has to restart it by hand after upgrading.
|
|
4
7
|
|
|
5
8
|
import { spawnSync } from 'node:child_process'
|
|
6
9
|
import { createHash } from 'node:crypto'
|
|
@@ -8,7 +11,14 @@ import fs from 'node:fs'
|
|
|
8
11
|
import path from 'node:path'
|
|
9
12
|
import { compareSemver } from '@contrast/runtime-delivery'
|
|
10
13
|
import { getCliVersion } from '../../src/cli-version'
|
|
11
|
-
import {
|
|
14
|
+
import { desktopHostDelivery, desktopHostPlatform } from '../../src/desktop-host-delivery'
|
|
15
|
+
import {
|
|
16
|
+
isDaemonLockfileFresh,
|
|
17
|
+
isSootsimDevCheckout,
|
|
18
|
+
readActiveRuntime,
|
|
19
|
+
readDaemonLockfile,
|
|
20
|
+
runtimeDir,
|
|
21
|
+
} from '../../src/home-paths'
|
|
12
22
|
import { resolveRNXAppConfig } from '../app-config'
|
|
13
23
|
import {
|
|
14
24
|
DEFAULT_CLI_RELEASE_ORIGIN,
|
|
@@ -17,7 +27,9 @@ import {
|
|
|
17
27
|
} from '../cli-update'
|
|
18
28
|
import { peachExit } from '../run-rnx'
|
|
19
29
|
import { fetchRuntimeReleaseNotes, formatRuntimeReleaseNotes } from '../runtime-notes'
|
|
30
|
+
import { rnxSelfInvocation } from '../self-invocation'
|
|
20
31
|
import { IS_STANDALONE } from '../standalone'
|
|
32
|
+
import { getDaemonServiceStatus } from './daemon'
|
|
21
33
|
import { runRuntime } from './runtime'
|
|
22
34
|
|
|
23
35
|
const SHA256_PATTERN = /^[a-f0-9]{64}$/
|
|
@@ -88,20 +100,51 @@ export async function runUpgrade(
|
|
|
88
100
|
? await fetchRuntimeReleaseNotes(installedRuntime)
|
|
89
101
|
: null
|
|
90
102
|
|
|
103
|
+
if (desktopHostPlatform() === 'linux-x64') {
|
|
104
|
+
// the first headless open would otherwise download the host it attaches
|
|
105
|
+
console.log('\nnative host:')
|
|
106
|
+
const host = await desktopHostDelivery().install({ quiet: true })
|
|
107
|
+
console.log(
|
|
108
|
+
` result: v${host.version} ${host.installed ? 'installed' : 'already current'}`,
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
|
|
91
112
|
console.log('\ncli:')
|
|
92
|
-
await upgradeCli({ ...options, cliVersion })
|
|
113
|
+
const cliChanged = await upgradeCli({ ...options, cliVersion })
|
|
114
|
+
if (cliChanged || readActiveRuntime() !== beforeRuntime) restartRunningDaemon()
|
|
93
115
|
|
|
94
116
|
if (installedRuntime && options.includeReleaseNotes !== false) {
|
|
95
117
|
console.log(`\n${formatRuntimeReleaseNotes(installedRuntime, releaseNotes)}`)
|
|
96
118
|
}
|
|
97
119
|
}
|
|
98
120
|
|
|
99
|
-
|
|
121
|
+
// the daemon process holds the cli code and runtime it started with. the
|
|
122
|
+
// service points at the executable path upgrade just replaced, so restarting
|
|
123
|
+
// it through the new executable is all a running daemon needs.
|
|
124
|
+
function restartRunningDaemon(): void {
|
|
125
|
+
if (!getDaemonServiceStatus().installed) return
|
|
126
|
+
if (!isDaemonLockfileFresh(readDaemonLockfile())) return
|
|
127
|
+
console.log('\ndaemon:')
|
|
128
|
+
const invocation = rnxSelfInvocation()
|
|
129
|
+
const result = spawnSync(
|
|
130
|
+
invocation.executable,
|
|
131
|
+
[...invocation.prefixArgs, 'daemon', 'restart'],
|
|
132
|
+
{ stdio: 'inherit' },
|
|
133
|
+
)
|
|
134
|
+
if (result.status !== 0) {
|
|
135
|
+
throw new Error(
|
|
136
|
+
`the background daemon did not restart onto the upgraded peach (exit ${result.status}); check \`peach daemon logs\``,
|
|
137
|
+
)
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** returns whether the executable was replaced. */
|
|
142
|
+
export async function upgradeCli(options: UpgradeOptions = {}): Promise<boolean> {
|
|
100
143
|
const standalone = options.standalone ?? IS_STANDALONE
|
|
101
144
|
if (!standalone) {
|
|
102
145
|
if (isSootsimDevCheckout()) {
|
|
103
146
|
console.log(' running from the Contrast checkout; pull instead of upgrading')
|
|
104
|
-
return
|
|
147
|
+
return false
|
|
105
148
|
}
|
|
106
149
|
throw new Error(
|
|
107
150
|
'this is not the standalone peach executable; reinstall from https://peachsim.com/install.sh',
|
|
@@ -117,11 +160,11 @@ export async function upgradeCli(options: UpgradeOptions = {}): Promise<void> {
|
|
|
117
160
|
options.cliVersion ?? (await refreshCliUpdateCache({ releaseOrigin })).latestVersion
|
|
118
161
|
if (options.cliVersion === current) {
|
|
119
162
|
console.log(` v${current} (requested)`)
|
|
120
|
-
return
|
|
163
|
+
return false
|
|
121
164
|
}
|
|
122
165
|
if (!options.cliVersion && compareSemver(latest, current) <= 0) {
|
|
123
166
|
console.log(` v${current} (latest)`)
|
|
124
|
-
return
|
|
167
|
+
return false
|
|
125
168
|
}
|
|
126
169
|
|
|
127
170
|
const artifact = cliArtifactName()
|
|
@@ -157,6 +200,7 @@ export async function upgradeCli(options: UpgradeOptions = {}): Promise<void> {
|
|
|
157
200
|
fs.rmSync(tempDir, { recursive: true, force: true })
|
|
158
201
|
}
|
|
159
202
|
console.log(` updated to v${latest}`)
|
|
203
|
+
return true
|
|
160
204
|
}
|
|
161
205
|
|
|
162
206
|
function cliArtifactName(): string {
|
package/cli/desktop-companion.ts
CHANGED
|
@@ -143,7 +143,7 @@ function findWindowsInstall(): DesktopCompanionInstall | null {
|
|
|
143
143
|
|
|
144
144
|
export interface DesktopCompanionOptions {
|
|
145
145
|
// the native host: PEACH_DESKTOP_APP, else the active version
|
|
146
|
-
// `peach desktop install --native`
|
|
146
|
+
// explicit `peach desktop install --native` places the mac app in /Applications.
|
|
147
147
|
native?: boolean
|
|
148
148
|
}
|
|
149
149
|
|