peachsim 0.1.2206 → 0.1.2208
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/bridge-diagnostics.ts +4 -4
- package/cli/bridge-flow-runner.ts +33 -33
- package/cli/browser-evals.ts +2 -2
- package/cli/commands/control.ts +1 -1
- package/cli/commands/cpu-profile.ts +5 -4
- package/cli/commands/debug.ts +3 -3
- package/cli/commands/diagnose.ts +2 -2
- package/cli/commands/flow.ts +7 -7
- package/cli/commands/inspect/core.ts +22 -22
- package/cli/commands/inspect/get-node.ts +2 -2
- package/cli/commands/inspect/shared.ts +2 -2
- package/cli/commands/inspect/wait-event.ts +1 -1
- package/cli/commands/inspect.ts +33 -33
- package/cli/commands/record-three.ts +17 -17
- package/cli/commands/record.ts +44 -40
- package/cli/commands/shell-boolean-mode.ts +1 -1
- package/cli/commands/slides.ts +5 -3
- package/cli/commands/three-mode.ts +3 -3
- package/cli/commands/upload.ts +8 -8
- package/cli/drivers/types.ts +1 -1
- package/cli/runtime-diagnostics.ts +2 -2
- package/cli/scene-video.ts +5 -3
- package/cli/send-to-box.ts +1 -1
- package/cli/ws-bridge.ts +3 -3
- 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 +1 -1
- package/dist-lib/bridge-contract.mjs +1 -1
- package/dist-lib/bundle-channel.cjs +6 -6
- 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 +4 -4
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/expo-swift-bundle.cjs +4 -4
- 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 +7 -7
- package/dist-lib/host/fetch-proxy-handler.cjs +4 -4
- 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 +10 -10
- 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 +1 -1
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro-fingerprint-registry.cjs +1 -1
- package/dist-lib/metro-fingerprint-registry.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +1 -1
- package/dist-lib/metro-production-bundle.mjs +1 -1
- package/dist-lib/metro.cjs +4 -4
- package/dist-lib/native-app-identity-project.cjs +2 -2
- package/dist-lib/native-app-identity-project.mjs +2 -2
- 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/pdfium-raster.cjs +1 -1
- package/dist-lib/pdfium-raster.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/public-origins-lib-esm.json +24 -24
- package/dist-lib/public-origins-lib.json +53 -53
- package/dist-lib/react-native-host-modules.cjs +1 -1
- package/dist-lib/react-native-host-modules.mjs +1 -1
- package/dist-lib/reap-browser.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +23 -23
- package/dist-lib/sdk.mjs +23 -23
- package/dist-lib/skills.cjs +55 -55
- package/dist-lib/swift-compile.cjs +2 -2
- package/dist-lib/swift-compile.mjs +2 -2
- package/dist-lib/swift-package.cjs +1 -1
- package/dist-lib/swift-package.mjs +1 -1
- package/dist-lib/swift-submit.cjs +1 -1
- package/dist-lib/swift-submit.mjs +1 -1
- package/dist-lib/swift-toolchain.cjs +1 -1
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite-swift.cjs +3 -3
- package/dist-lib/vite.cjs +4 -4
- package/dist-lib/worklet-executable.cjs +1 -1
- package/dist-lib/worklet-executable.mjs +1 -1
- package/dist-types/packages/peach-engine/src/engine/image-loader.d.ts +1 -1
- package/dist-types/packages/peach-engine/src/engine/node.d.ts +3 -0
- package/dist-types/packages/peach-engine/src/settings/store.d.ts +1 -0
- package/package.json +1 -1
- package/runtime-companion.json +1 -1
- package/sdk/ios/System/Library/Frameworks/Foundation.framework/Headers/Foundation.apinotes +0 -8
|
@@ -150,8 +150,8 @@ export async function printBridgeStateSummary(bridge: WsBridge) {
|
|
|
150
150
|
const state = (await bridge.send({
|
|
151
151
|
type: 'evaluate',
|
|
152
152
|
code: `(async () => {
|
|
153
|
-
const test =
|
|
154
|
-
const mainShell =
|
|
153
|
+
const test = globalThis.__sootsimTest
|
|
154
|
+
const mainShell = globalThis.SootSim?.bridges?.mainShell
|
|
155
155
|
let shell = null
|
|
156
156
|
try {
|
|
157
157
|
shell = typeof mainShell?.getState === 'function' ? await mainShell.getState() : null
|
|
@@ -162,9 +162,9 @@ export async function printBridgeStateSummary(bridge: WsBridge) {
|
|
|
162
162
|
} catch {}
|
|
163
163
|
return {
|
|
164
164
|
url: window.location.href,
|
|
165
|
-
simId:
|
|
165
|
+
simId: globalThis.__sootsimSimId || null,
|
|
166
166
|
nodeCount,
|
|
167
|
-
mode:
|
|
167
|
+
mode: globalThis.__sootsimRenderHost ? 'render-worker' : 'main-thread',
|
|
168
168
|
shell: shell
|
|
169
169
|
? {
|
|
170
170
|
state: shell.state || null,
|
|
@@ -523,7 +523,7 @@ type FocusedTextInputInfo = {
|
|
|
523
523
|
}
|
|
524
524
|
type ShellState = Record<string, unknown>
|
|
525
525
|
|
|
526
|
-
// shape of
|
|
526
|
+
// shape of globalThis.__sootsimShellPerf.stop() — the shell worker frame profile
|
|
527
527
|
// (the worker that paints app pixels) merged with the render-profile counters.
|
|
528
528
|
// see sootsim-engine shell-worker.ts stopShellFrameProfile.
|
|
529
529
|
export interface SootSimFlowProfileResult {
|
|
@@ -1291,7 +1291,7 @@ export class SootSimBridgeFlowRunner {
|
|
|
1291
1291
|
format?: string
|
|
1292
1292
|
startedAtMs?: number
|
|
1293
1293
|
}>(`(() => {
|
|
1294
|
-
const rec =
|
|
1294
|
+
const rec = globalThis.__sootsimRecorder
|
|
1295
1295
|
if (!rec) return { ok: false, error: 'recorder unavailable on this page' }
|
|
1296
1296
|
const format = ${JSON.stringify(this.opts.recordingFormat ?? 'webm')}
|
|
1297
1297
|
if (rec.state() === 'recording') return { ok: true, format }
|
|
@@ -1312,12 +1312,12 @@ export class SootSimBridgeFlowRunner {
|
|
|
1312
1312
|
// stops the recorder and leaves no half-started state to skip past.
|
|
1313
1313
|
try {
|
|
1314
1314
|
await this.evaluate(`(() => {
|
|
1315
|
-
const recorder =
|
|
1315
|
+
const recorder = globalThis.SootSim?.bridges?.eventRecorder ?? globalThis.__sootsimEventRecorder
|
|
1316
1316
|
if (!recorder?.isRecording?.()) return
|
|
1317
1317
|
return recorder.markVisibleStart(${JSON.stringify(startedAtMs)})
|
|
1318
1318
|
})()`)
|
|
1319
1319
|
} catch (error) {
|
|
1320
|
-
await this.evaluate(`
|
|
1320
|
+
await this.evaluate(`globalThis.__sootsimRecorder.stop()`).catch(() => {})
|
|
1321
1321
|
throw error
|
|
1322
1322
|
}
|
|
1323
1323
|
this.recordingStartedAtMs = startedAtMs
|
|
@@ -1432,7 +1432,7 @@ export class SootSimBridgeFlowRunner {
|
|
|
1432
1432
|
mime?: string
|
|
1433
1433
|
durationMs: number
|
|
1434
1434
|
profile?: ProfileFile | null
|
|
1435
|
-
}>(`
|
|
1435
|
+
}>(`globalThis.__sootsimRecorder.stop()`)
|
|
1436
1436
|
if (!stopped?.ok) {
|
|
1437
1437
|
this.recordingStartedAtMs = null
|
|
1438
1438
|
this.lastRecordingProfile = null
|
|
@@ -1457,7 +1457,7 @@ export class SootSimBridgeFlowRunner {
|
|
|
1457
1457
|
done: boolean
|
|
1458
1458
|
mime: string
|
|
1459
1459
|
} | null>(
|
|
1460
|
-
`
|
|
1460
|
+
`globalThis.__sootsimRecorder.getBlobBase64({ offset: ${offset}, chunk: ${
|
|
1461
1461
|
2 * 1024 * 1024
|
|
1462
1462
|
} })`,
|
|
1463
1463
|
)
|
|
@@ -1517,7 +1517,7 @@ export class SootSimBridgeFlowRunner {
|
|
|
1517
1517
|
|
|
1518
1518
|
private async captureAccessibilityTree(): Promise<PeachAccessibilityNode[]> {
|
|
1519
1519
|
const tree = await this.evaluate(`(async () => {
|
|
1520
|
-
const test =
|
|
1520
|
+
const test = globalThis.__sootsimTest
|
|
1521
1521
|
if (!test || typeof test.captureAccessibilityTree !== 'function') throw new Error('engine accessibility snapshot is unavailable')
|
|
1522
1522
|
return await test.captureAccessibilityTree()
|
|
1523
1523
|
})()`)
|
|
@@ -1593,7 +1593,7 @@ export class SootSimBridgeFlowRunner {
|
|
|
1593
1593
|
private async findElementScoped(opts: FlowTargetSelector, preferHittable = false) {
|
|
1594
1594
|
const screen = await this.screenBounds()
|
|
1595
1595
|
const candidates = await this.evaluate<any[]>(`(async () => {
|
|
1596
|
-
const test =
|
|
1596
|
+
const test = globalThis.__sootsimTest
|
|
1597
1597
|
if (!test || !test.queryAll) return null
|
|
1598
1598
|
const selector = ${JSON.stringify(opts)}
|
|
1599
1599
|
const compile = ${accessibilityTextMatcher.toString()}
|
|
@@ -1774,7 +1774,7 @@ export class SootSimBridgeFlowRunner {
|
|
|
1774
1774
|
if (candidates.length < 2) return candidates[0] ?? null
|
|
1775
1775
|
const nodeIds = candidates.map((node) => node.nodeId)
|
|
1776
1776
|
const index = await this.evaluate<number>(`(async () => {
|
|
1777
|
-
const test =
|
|
1777
|
+
const test = globalThis.__sootsimTest
|
|
1778
1778
|
for (const [index, nodeId] of ${JSON.stringify(nodeIds)}.entries()) {
|
|
1779
1779
|
if (typeof nodeId !== 'number') continue
|
|
1780
1780
|
const resolved = await test.resolveTapTarget(nodeId)
|
|
@@ -1791,7 +1791,7 @@ export class SootSimBridgeFlowRunner {
|
|
|
1791
1791
|
|
|
1792
1792
|
private async resolveTapTarget(nodeId: number) {
|
|
1793
1793
|
return this.evaluate<any>(`(async () => {
|
|
1794
|
-
const test =
|
|
1794
|
+
const test = globalThis.__sootsimTest
|
|
1795
1795
|
if (!test?.resolveTapTarget) return null
|
|
1796
1796
|
return await test.resolveTapTarget(${nodeId})
|
|
1797
1797
|
})()`)
|
|
@@ -1807,7 +1807,7 @@ export class SootSimBridgeFlowRunner {
|
|
|
1807
1807
|
? { id: opts.id, testID: opts.id, text: null }
|
|
1808
1808
|
: { id: null, testID: null, text: opts.text ?? null }
|
|
1809
1809
|
return this.evaluate<any>(`(async () => {
|
|
1810
|
-
const test =
|
|
1810
|
+
const test = globalThis.__sootsimTest
|
|
1811
1811
|
if (!test) return null
|
|
1812
1812
|
let point = { x: ${x}, y: ${y} }
|
|
1813
1813
|
const resolved = await test.resolveTapTarget(${nodeId})
|
|
@@ -1830,7 +1830,7 @@ export class SootSimBridgeFlowRunner {
|
|
|
1830
1830
|
|
|
1831
1831
|
private async activatePressAt(x: number, y: number) {
|
|
1832
1832
|
return this.evaluate<any>(`(async () => {
|
|
1833
|
-
const test =
|
|
1833
|
+
const test = globalThis.__sootsimTest
|
|
1834
1834
|
if (!test?.activatePressAt) return null
|
|
1835
1835
|
const direct = await test.activatePressAt(${x}, ${y})
|
|
1836
1836
|
if (direct?.ok) {
|
|
@@ -1878,7 +1878,7 @@ export class SootSimBridgeFlowRunner {
|
|
|
1878
1878
|
// which no tree, layout, scroll or prop write could move any element.
|
|
1879
1879
|
private async geometryRevision(): Promise<string | null> {
|
|
1880
1880
|
const revision = await this.evaluate(
|
|
1881
|
-
`(async () =>
|
|
1881
|
+
`(async () => globalThis.__sootsimTest?.getGeometryRevision?.())()`,
|
|
1882
1882
|
)
|
|
1883
1883
|
return typeof revision === 'string' ? revision : null
|
|
1884
1884
|
}
|
|
@@ -2345,7 +2345,7 @@ export class SootSimBridgeFlowRunner {
|
|
|
2345
2345
|
private async isKeyboardVisible(): Promise<boolean> {
|
|
2346
2346
|
const visible = await this.evaluate<boolean>(`(() => {
|
|
2347
2347
|
const keyboard =
|
|
2348
|
-
|
|
2348
|
+
globalThis.__sootsimKeyboard ?? globalThis.SootSim?.bridges?.keyboard ?? null
|
|
2349
2349
|
return !!keyboard?.isVisible?.()
|
|
2350
2350
|
})()`)
|
|
2351
2351
|
return visible === true
|
|
@@ -2480,11 +2480,11 @@ export class SootSimBridgeFlowRunner {
|
|
|
2480
2480
|
type: 'evaluate',
|
|
2481
2481
|
simId: this.opts.simId,
|
|
2482
2482
|
code: `(() => {
|
|
2483
|
-
const c =
|
|
2483
|
+
const c = globalThis.__sootsimConsole
|
|
2484
2484
|
return {
|
|
2485
2485
|
errors: c?.getErrors?.() ?? [],
|
|
2486
2486
|
warnings: c?.getWarnings?.() ?? [],
|
|
2487
|
-
requests: (
|
|
2487
|
+
requests: (globalThis.__sootsimGetFailedRequests?.() ?? []),
|
|
2488
2488
|
}
|
|
2489
2489
|
})()`,
|
|
2490
2490
|
})) as SootSimFlowConsole
|
|
@@ -2542,7 +2542,7 @@ export class SootSimBridgeFlowRunner {
|
|
|
2542
2542
|
manifest?: unknown
|
|
2543
2543
|
}>(`(async () => {
|
|
2544
2544
|
const out = {
|
|
2545
|
-
simId:
|
|
2545
|
+
simId: globalThis.__sootsimBridge?.id ?? globalThis.SootSim?.state?.simId ?? null,
|
|
2546
2546
|
url: location.href,
|
|
2547
2547
|
title: document.title,
|
|
2548
2548
|
hidden: document.hidden,
|
|
@@ -2596,8 +2596,8 @@ export class SootSimBridgeFlowRunner {
|
|
|
2596
2596
|
// full layout, style, a11y, transforms. the `--json` describe output
|
|
2597
2597
|
// shape; inlined here so we don't depend on the cli reentering.
|
|
2598
2598
|
const describeJson = await safeEval<any>(`(async () => {
|
|
2599
|
-
const t =
|
|
2600
|
-
const mainShell =
|
|
2599
|
+
const t = globalThis.__sootsimTest
|
|
2600
|
+
const mainShell = globalThis.SootSim?.bridges?.mainShell
|
|
2601
2601
|
if (!t) return { error: 'no test bridge' }
|
|
2602
2602
|
let shell = null
|
|
2603
2603
|
try {
|
|
@@ -2610,19 +2610,19 @@ export class SootSimBridgeFlowRunner {
|
|
|
2610
2610
|
|
|
2611
2611
|
// every animation the settle check can name, with its kind, priority and visibility
|
|
2612
2612
|
const animations = await safeEval<unknown>(
|
|
2613
|
-
`(async () => await
|
|
2613
|
+
`(async () => await globalThis.__sootsimTest?.listAnimations?.())()`,
|
|
2614
2614
|
)
|
|
2615
2615
|
if (animations) write('animations.json', JSON.stringify(animations, null, 2))
|
|
2616
2616
|
|
|
2617
2617
|
// 4. accessibility tree (flat text — what voiceover would read)
|
|
2618
2618
|
const a11y = await safeEval<string>(
|
|
2619
|
-
`(async () => await
|
|
2619
|
+
`(async () => await globalThis.__sootsimTest?.dumpAccessibilityTree?.(20))()`,
|
|
2620
2620
|
)
|
|
2621
2621
|
if (typeof a11y === 'string') write('a11y.txt', a11y)
|
|
2622
2622
|
|
|
2623
2623
|
// 5. tree dump (nested — useful for layout bugs)
|
|
2624
2624
|
const tree = await safeEval<string>(
|
|
2625
|
-
`(async () => await
|
|
2625
|
+
`(async () => await globalThis.__sootsimTest?.dumpTree?.(15))()`,
|
|
2626
2626
|
)
|
|
2627
2627
|
if (typeof tree === 'string') write('tree.txt', tree)
|
|
2628
2628
|
|
|
@@ -2816,14 +2816,14 @@ export class SootSimBridgeFlowRunner {
|
|
|
2816
2816
|
frameIndex?: number
|
|
2817
2817
|
}>(
|
|
2818
2818
|
`(async () => {
|
|
2819
|
-
const lockstep =
|
|
2819
|
+
const lockstep = globalThis.SootSim?.bridges?.lockstepCapture
|
|
2820
2820
|
if (!lockstep || typeof lockstep.begin !== 'function') {
|
|
2821
2821
|
return { ok: false, error: 'lockstep capture bridge unavailable' }
|
|
2822
2822
|
}
|
|
2823
|
-
let controller =
|
|
2823
|
+
let controller = globalThis.__peachFlowAnimationClockController
|
|
2824
2824
|
if (!controller) {
|
|
2825
2825
|
controller = await lockstep.begin(${JSON.stringify(fps)})
|
|
2826
|
-
|
|
2826
|
+
globalThis.__peachFlowAnimationClockController = controller
|
|
2827
2827
|
}
|
|
2828
2828
|
let receipt = controller.initialFrame
|
|
2829
2829
|
for (const ms of ${JSON.stringify(steps)}) {
|
|
@@ -2847,13 +2847,13 @@ export class SootSimBridgeFlowRunner {
|
|
|
2847
2847
|
if (!this.animationClockLocked) return
|
|
2848
2848
|
this.animationClockLocked = false
|
|
2849
2849
|
await this.evaluate(`(() => {
|
|
2850
|
-
const controller =
|
|
2851
|
-
|
|
2850
|
+
const controller = globalThis.__peachFlowAnimationClockController
|
|
2851
|
+
globalThis.__peachFlowAnimationClockController = null
|
|
2852
2852
|
if (controller && typeof controller.end === 'function') {
|
|
2853
2853
|
controller.end()
|
|
2854
2854
|
return
|
|
2855
2855
|
}
|
|
2856
|
-
|
|
2856
|
+
globalThis.SootSim?.bridges?.lockstepCapture?.end?.()
|
|
2857
2857
|
})()`).catch(() => {})
|
|
2858
2858
|
}
|
|
2859
2859
|
|
|
@@ -3235,10 +3235,10 @@ export class SootSimBridgeFlowRunner {
|
|
|
3235
3235
|
|
|
3236
3236
|
async startProfile() {
|
|
3237
3237
|
const result = await this.evaluate<any>(`(async () => {
|
|
3238
|
-
if (!
|
|
3238
|
+
if (!globalThis.__sootsimShellPerf) {
|
|
3239
3239
|
return { error: "shell frame profile unavailable (__sootsimShellPerf missing on the page)" }
|
|
3240
3240
|
}
|
|
3241
|
-
await
|
|
3241
|
+
await globalThis.__sootsimShellPerf.start()
|
|
3242
3242
|
return { started: true }
|
|
3243
3243
|
})()`)
|
|
3244
3244
|
if (result?.error) {
|
|
@@ -3249,10 +3249,10 @@ export class SootSimBridgeFlowRunner {
|
|
|
3249
3249
|
|
|
3250
3250
|
async stopProfile(): Promise<SootSimFlowProfileResult> {
|
|
3251
3251
|
const result = await this.evaluate<any>(`(async () => {
|
|
3252
|
-
if (!
|
|
3252
|
+
if (!globalThis.__sootsimShellPerf) {
|
|
3253
3253
|
return { error: "shell frame profile unavailable (__sootsimShellPerf missing on the page)" }
|
|
3254
3254
|
}
|
|
3255
|
-
return await
|
|
3255
|
+
return await globalThis.__sootsimShellPerf.stop()
|
|
3256
3256
|
})()`)
|
|
3257
3257
|
|
|
3258
3258
|
this.profilingEnabled = false
|
|
@@ -3454,7 +3454,7 @@ export class SootSimBridgeFlowRunner {
|
|
|
3454
3454
|
const dataUrl = `data:${mimeType};base64,${bytes.toString('base64')}`
|
|
3455
3455
|
const added = await this.evaluate<{ ok: boolean; error?: string }>(
|
|
3456
3456
|
`(async () => {
|
|
3457
|
-
const add =
|
|
3457
|
+
const add = globalThis.__sootsimAddPhotoDataUrl
|
|
3458
3458
|
if (typeof add !== 'function') {
|
|
3459
3459
|
return { ok: false, error: 'photo library bridge unavailable' }
|
|
3460
3460
|
}
|
package/cli/browser-evals.ts
CHANGED
|
@@ -19,7 +19,7 @@ export interface SampleRect {
|
|
|
19
19
|
// returns null on miss so the caller can report a clear not-found error.
|
|
20
20
|
export function buildResolveRectEval(matcher: { id?: string; text?: string }): string {
|
|
21
21
|
return `(async () => {
|
|
22
|
-
const __t =
|
|
22
|
+
const __t = globalThis.__sootsimTest
|
|
23
23
|
if (!__t) throw new Error('__sootsimTest not available')
|
|
24
24
|
const __id = ${JSON.stringify(matcher.id || '')}
|
|
25
25
|
const __text = ${JSON.stringify(matcher.text || '')}
|
|
@@ -48,7 +48,7 @@ export function buildResolveRectEval(matcher: { id?: string; text?: string }): s
|
|
|
48
48
|
export function buildSampleColorEval(rect: SampleRect): string {
|
|
49
49
|
return `(async () => {
|
|
50
50
|
const __rect = ${JSON.stringify(rect)}
|
|
51
|
-
const __screenshot =
|
|
51
|
+
const __screenshot = globalThis.__sootsimScreenshot
|
|
52
52
|
if (typeof __screenshot !== 'function') {
|
|
53
53
|
throw new Error('screenshot bridge not installed')
|
|
54
54
|
}
|
package/cli/commands/control.ts
CHANGED
|
@@ -1307,7 +1307,7 @@ async function waitForTreeStable(
|
|
|
1307
1307
|
opts: { stableMs: number; maxMs: number },
|
|
1308
1308
|
): Promise<void> {
|
|
1309
1309
|
const deadline = Date.now() + opts.maxMs
|
|
1310
|
-
const probeCode = `(async () => (await
|
|
1310
|
+
const probeCode = `(async () => (await globalThis.__sootsimTest?.getNodeCount?.()) || 0)()`
|
|
1311
1311
|
const bridge = createBridge(wsPort, {
|
|
1312
1312
|
commandTimeoutMs: 2000,
|
|
1313
1313
|
simId,
|
|
@@ -701,13 +701,14 @@ Writes a page profile, worker profiles, and a manifest alongside the output.
|
|
|
701
701
|
// with the native host attached, the engine's workers are realm threads in the host, reached
|
|
702
702
|
// through the page; they record over the same window as the browser targets
|
|
703
703
|
const hostRealms =
|
|
704
|
-
(await evaluatePage(
|
|
705
|
-
|
|
704
|
+
(await evaluatePage(
|
|
705
|
+
`typeof globalThis.__peachNative?.cpuProfile === 'function'`,
|
|
706
|
+
)) === true
|
|
706
707
|
const hostTargets: AttachedTarget[] = []
|
|
707
708
|
if (hostRealms) {
|
|
708
709
|
const startedAtMs = performance.now()
|
|
709
710
|
const realms = await evaluatePage(
|
|
710
|
-
`
|
|
711
|
+
`globalThis.__peachNative.cpuProfile('start', ${sampleInterval * 1000})`,
|
|
711
712
|
)
|
|
712
713
|
for (const realm of Array.isArray(realms) ? realms : []) {
|
|
713
714
|
hostTargets.push({
|
|
@@ -768,7 +769,7 @@ Writes a page profile, worker profiles, and a manifest alongside the output.
|
|
|
768
769
|
}),
|
|
769
770
|
)
|
|
770
771
|
if (hostRealms) {
|
|
771
|
-
const stopped = await evaluatePage(`
|
|
772
|
+
const stopped = await evaluatePage(`globalThis.__peachNative.cpuProfile('stop', 0)`)
|
|
772
773
|
const stoppedAtMs = performance.now()
|
|
773
774
|
for (const realm of Array.isArray(stopped) ? stopped : []) {
|
|
774
775
|
const target = hostTargets.find(
|
package/cli/commands/debug.ts
CHANGED
|
@@ -311,7 +311,7 @@ function readNumberFlag(args: string[], flag: string): number | null {
|
|
|
311
311
|
async function runImageAudit(bridge: WsBridge): Promise<ImageAuditReport> {
|
|
312
312
|
await call(
|
|
313
313
|
bridge,
|
|
314
|
-
"
|
|
314
|
+
"globalThis.__sootsimCompositor.getStats(false, false, undefined, 'enable').then(() => 'enabled')",
|
|
315
315
|
)
|
|
316
316
|
let stats: { imageAudit?: ImageAuditReport | null }
|
|
317
317
|
try {
|
|
@@ -319,7 +319,7 @@ async function runImageAudit(bridge: WsBridge): Promise<ImageAuditReport> {
|
|
|
319
319
|
} finally {
|
|
320
320
|
stats = await call(
|
|
321
321
|
bridge,
|
|
322
|
-
"
|
|
322
|
+
"globalThis.__sootsimCompositor.getStats(false, false, undefined, 'disable').then((s) => ({ imageAudit: s.imageAudit }))",
|
|
323
323
|
)
|
|
324
324
|
}
|
|
325
325
|
const report = stats?.imageAudit
|
|
@@ -347,7 +347,7 @@ async function runTargetedImageAudit(
|
|
|
347
347
|
bridge,
|
|
348
348
|
`(async () => {
|
|
349
349
|
const input = ${JSON.stringify(targets)};
|
|
350
|
-
const compositor =
|
|
350
|
+
const compositor = globalThis.__sootsimCompositor;
|
|
351
351
|
let capture;
|
|
352
352
|
let receipt;
|
|
353
353
|
let audit;
|
package/cli/commands/diagnose.ts
CHANGED
|
@@ -229,7 +229,7 @@ async function fetchNetwork(
|
|
|
229
229
|
const result = (await bridge.send({
|
|
230
230
|
type: 'evaluate',
|
|
231
231
|
code: `(() => {
|
|
232
|
-
const obs =
|
|
232
|
+
const obs = globalThis.__sootsimObservability;
|
|
233
233
|
if (!obs) return { ok: false };
|
|
234
234
|
return { ok: true, entries: obs.network.getSnapshot() };
|
|
235
235
|
})()`,
|
|
@@ -296,7 +296,7 @@ async function fetchConsoleErrors(
|
|
|
296
296
|
const result = (await bridge.send({
|
|
297
297
|
type: 'evaluate',
|
|
298
298
|
code: `(() => {
|
|
299
|
-
const obs =
|
|
299
|
+
const obs = globalThis.__sootsimObservability;
|
|
300
300
|
if (!obs) return { ok: false };
|
|
301
301
|
return { ok: true, entries: obs.logs.getSnapshot() };
|
|
302
302
|
})()`,
|
package/cli/commands/flow.ts
CHANGED
|
@@ -811,7 +811,7 @@ flow extension:
|
|
|
811
811
|
type: 'evaluate',
|
|
812
812
|
simId: driver.simId,
|
|
813
813
|
code: `(() => {
|
|
814
|
-
const r =
|
|
814
|
+
const r = globalThis.SootSim?.bridges?.eventRecorder ?? globalThis.__sootsimEventRecorder
|
|
815
815
|
return r?.start?.() ?? false
|
|
816
816
|
})()`,
|
|
817
817
|
})
|
|
@@ -909,13 +909,13 @@ flow extension:
|
|
|
909
909
|
if (preview) {
|
|
910
910
|
// start the preview event recorder on the tab so agent-driven taps
|
|
911
911
|
// (via sootsim:agentAction) land in the capture stream for replay.
|
|
912
|
-
// some shells expose the recorder via
|
|
912
|
+
// some shells expose the recorder via globalThis.SootSim, others via
|
|
913
913
|
// the legacy alias only — try both.
|
|
914
914
|
const started = await bridge.send({
|
|
915
915
|
type: 'evaluate',
|
|
916
916
|
simId: driver.simId,
|
|
917
917
|
code: `(() => {
|
|
918
|
-
const r =
|
|
918
|
+
const r = globalThis.SootSim?.bridges?.eventRecorder ?? globalThis.__sootsimEventRecorder
|
|
919
919
|
const startedAtMs = Date.now()
|
|
920
920
|
return r?.start?.(startedAtMs) ? startedAtMs : null
|
|
921
921
|
})()`,
|
|
@@ -945,7 +945,7 @@ flow extension:
|
|
|
945
945
|
type: 'evaluate',
|
|
946
946
|
simId: driver.simId,
|
|
947
947
|
code: `(() => {
|
|
948
|
-
const r =
|
|
948
|
+
const r = globalThis.SootSim?.bridges?.eventRecorder ?? globalThis.__sootsimEventRecorder
|
|
949
949
|
return r?.stop?.() ?? []
|
|
950
950
|
})()`,
|
|
951
951
|
})) as Array<Record<string, any>>
|
|
@@ -1000,7 +1000,7 @@ flow extension:
|
|
|
1000
1000
|
type: 'evaluate',
|
|
1001
1001
|
simId: driver.simId,
|
|
1002
1002
|
code: `(() => {
|
|
1003
|
-
const r =
|
|
1003
|
+
const r = globalThis.SootSim?.bridges?.eventRecorder ?? globalThis.__sootsimEventRecorder
|
|
1004
1004
|
return r?.stop?.() ?? []
|
|
1005
1005
|
})()`,
|
|
1006
1006
|
})) as Array<Record<string, any>>
|
|
@@ -1294,7 +1294,7 @@ async function startPreviewSceneRecording(
|
|
|
1294
1294
|
await bridge.send({
|
|
1295
1295
|
type: 'evaluate',
|
|
1296
1296
|
simId,
|
|
1297
|
-
code: `
|
|
1297
|
+
code: `globalThis.SootSim.bridges.sceneStream.run({ action: 'recordStart' })`,
|
|
1298
1298
|
})
|
|
1299
1299
|
return true
|
|
1300
1300
|
} catch (err) {
|
|
@@ -1315,7 +1315,7 @@ async function stopPreviewSceneRecording(
|
|
|
1315
1315
|
type: 'evaluate',
|
|
1316
1316
|
simId,
|
|
1317
1317
|
code: `(async () => {
|
|
1318
|
-
const { bytes } = await
|
|
1318
|
+
const { bytes } = await globalThis.SootSim.bridges.sceneStream.run({ action: 'recordStop' })
|
|
1319
1319
|
let text = ''
|
|
1320
1320
|
for (let i = 0; i < bytes.length; i += 0x8000)
|
|
1321
1321
|
text += String.fromCharCode(...bytes.subarray(i, i + 0x8000))
|
|
@@ -90,7 +90,7 @@ export function isInspectPickCommand(subcommand: string | null | undefined): boo
|
|
|
90
90
|
export async function isInspectModeActive(bridge: InspectBridge): Promise<boolean> {
|
|
91
91
|
const active = await bridge.send({
|
|
92
92
|
type: 'evaluate',
|
|
93
|
-
code: '
|
|
93
|
+
code: 'globalThis.__sootsimEngineState?.inspectActive === true',
|
|
94
94
|
})
|
|
95
95
|
return active === true
|
|
96
96
|
}
|
|
@@ -587,7 +587,7 @@ export function layoutGetNativeEval(opts: LayoutExtractionOptions = {}): string
|
|
|
587
587
|
const includeStyle = opts.styling === true
|
|
588
588
|
const filter = opts.filter?.trim().toLowerCase() ?? ''
|
|
589
589
|
return `(async () => {
|
|
590
|
-
const t =
|
|
590
|
+
const t = globalThis.__sootsimTest
|
|
591
591
|
if (!t || typeof t.listInspectable !== 'function') return []
|
|
592
592
|
const list = await t.listInspectable({})
|
|
593
593
|
if (!Array.isArray(list)) return []
|
|
@@ -751,7 +751,7 @@ export function layoutGetNativeEval(opts: LayoutExtractionOptions = {}): string
|
|
|
751
751
|
const textElements = elements.filter((element) => element.text && element.fontSize > 0)
|
|
752
752
|
if (!includeStyle || textElements.length === 0) return elements
|
|
753
753
|
|
|
754
|
-
const screenshot =
|
|
754
|
+
const screenshot = globalThis.SootSim && globalThis.SootSim.bridges && globalThis.SootSim.bridges.screenshot
|
|
755
755
|
if (typeof screenshot !== 'function') {
|
|
756
756
|
throw new Error('styled native layout requires the peach capture bridge')
|
|
757
757
|
}
|
|
@@ -1714,10 +1714,10 @@ export function consoleEntriesEval(level: 'error' | 'warn', limit: number): stri
|
|
|
1714
1714
|
out.push({ timestamp: ts, args: Array.isArray(e.args) ? e.args : [e.args], stack: e.stack || undefined, source: e.source || undefined })
|
|
1715
1715
|
}
|
|
1716
1716
|
// page-realm ws-bridge buffer first (richest stacks for page-origin errors)
|
|
1717
|
-
try { for (const e of (
|
|
1717
|
+
try { for (const e of (globalThis.__sootsimConsole?.${getter}(${limit}) || [])) push(e) } catch {}
|
|
1718
1718
|
// engine observability store — the always-on render-worker / forwarded path
|
|
1719
1719
|
try {
|
|
1720
|
-
const obs =
|
|
1720
|
+
const obs = globalThis.__sootsimObservability
|
|
1721
1721
|
const snap = obs && obs.logs && typeof obs.logs.getSnapshot === 'function' ? obs.logs.getSnapshot() : []
|
|
1722
1722
|
for (const e of snap) if (e && e.level === ${JSON.stringify(level)}) push(e)
|
|
1723
1723
|
} catch {}
|
|
@@ -1772,12 +1772,12 @@ export const MERGED_CONSOLE_COUNT_EVAL = `(() => {
|
|
|
1772
1772
|
else warnings++
|
|
1773
1773
|
}
|
|
1774
1774
|
try {
|
|
1775
|
-
const c =
|
|
1775
|
+
const c = globalThis.__sootsimConsole
|
|
1776
1776
|
for (const e of (c?.getErrors?.(200) || [])) add('error', e?.timestamp ?? e?.ts, e?.args)
|
|
1777
1777
|
for (const e of (c?.getWarnings?.(200) || [])) add('warn', e?.timestamp ?? e?.ts, e?.args)
|
|
1778
1778
|
} catch {}
|
|
1779
1779
|
try {
|
|
1780
|
-
const obs =
|
|
1780
|
+
const obs = globalThis.__sootsimObservability
|
|
1781
1781
|
const snap = obs && obs.logs && typeof obs.logs.getSnapshot === 'function' ? obs.logs.getSnapshot() : []
|
|
1782
1782
|
for (const e of snap) if (e) add(e.level, e.ts, e.args)
|
|
1783
1783
|
} catch {}
|
|
@@ -1789,7 +1789,7 @@ export const MERGED_CONSOLE_COUNT_EVAL = `(() => {
|
|
|
1789
1789
|
export async function clearConsole(bridge: InspectBridge): Promise<void> {
|
|
1790
1790
|
await bridge.send({
|
|
1791
1791
|
type: 'evaluate',
|
|
1792
|
-
code: '
|
|
1792
|
+
code: 'globalThis.__sootsimConsole?.clear(); globalThis.__sootsimObservability?.logs?.clear?.(); "cleared"',
|
|
1793
1793
|
})
|
|
1794
1794
|
}
|
|
1795
1795
|
|
|
@@ -1924,7 +1924,7 @@ export async function inspectLogs(bridge: InspectBridge): Promise<LogEntry[]> {
|
|
|
1924
1924
|
const res = (await bridge.send({
|
|
1925
1925
|
type: 'evaluate',
|
|
1926
1926
|
code: `(() => {
|
|
1927
|
-
const obs =
|
|
1927
|
+
const obs = globalThis.__sootsimObservability;
|
|
1928
1928
|
if (!obs) return { ok: false };
|
|
1929
1929
|
return { ok: true, entries: obs.logs.getSnapshot() };
|
|
1930
1930
|
})()`,
|
|
@@ -1937,7 +1937,7 @@ export async function inspectLogs(bridge: InspectBridge): Promise<LogEntry[]> {
|
|
|
1937
1937
|
export async function clearLogs(bridge: InspectBridge): Promise<void> {
|
|
1938
1938
|
await bridge.send({
|
|
1939
1939
|
type: 'evaluate',
|
|
1940
|
-
code: '
|
|
1940
|
+
code: 'globalThis.__sootsimObservability?.logs.clear(); "cleared"',
|
|
1941
1941
|
})
|
|
1942
1942
|
}
|
|
1943
1943
|
|
|
@@ -2085,7 +2085,7 @@ export async function inspectKeyboard(
|
|
|
2085
2085
|
const result = (await bridge.send({
|
|
2086
2086
|
type: 'evaluate',
|
|
2087
2087
|
code: `(() => {
|
|
2088
|
-
const kb =
|
|
2088
|
+
const kb = globalThis.__sootsimKeyboard
|
|
2089
2089
|
if (!kb || typeof kb.getLayout !== 'function') {
|
|
2090
2090
|
return { error: 'keyboard bridge getLayout() not available' }
|
|
2091
2091
|
}
|
|
@@ -2165,8 +2165,8 @@ export async function inspectScreens(bridge: InspectBridge): Promise<ScreensRepo
|
|
|
2165
2165
|
const payload = (await bridge.send({
|
|
2166
2166
|
type: 'evaluate',
|
|
2167
2167
|
code: `(async () => {
|
|
2168
|
-
const test =
|
|
2169
|
-
const kb =
|
|
2168
|
+
const test = globalThis.__sootsimTest
|
|
2169
|
+
const kb = globalThis.__sootsimKeyboard
|
|
2170
2170
|
const navSnap =
|
|
2171
2171
|
test && typeof test.getNavigationSnapshot === 'function'
|
|
2172
2172
|
? await test.getNavigationSnapshot()
|
|
@@ -2226,7 +2226,7 @@ export async function inspectDebugStatus(
|
|
|
2226
2226
|
if (bridge.plane === 'cloud' && !host) {
|
|
2227
2227
|
return (await inspectCloudDiagnostics(bridge)).channels
|
|
2228
2228
|
}
|
|
2229
|
-
return bridge.send({ type: 'evaluate', code: '
|
|
2229
|
+
return bridge.send({ type: 'evaluate', code: 'globalThis.__sootsimDebug.status()' })
|
|
2230
2230
|
}
|
|
2231
2231
|
|
|
2232
2232
|
// `debug flags` — the engine's debug feature flags.
|
|
@@ -2240,7 +2240,7 @@ export async function inspectDebugFlags(
|
|
|
2240
2240
|
availableChannels.map((channel) => [channel, channels.includes(channel)]),
|
|
2241
2241
|
)
|
|
2242
2242
|
}
|
|
2243
|
-
return bridge.send({ type: 'evaluate', code: '
|
|
2243
|
+
return bridge.send({ type: 'evaluate', code: 'globalThis.__sootsimDebug.flags()' })
|
|
2244
2244
|
}
|
|
2245
2245
|
|
|
2246
2246
|
export async function inspectDebugChannels(
|
|
@@ -2250,7 +2250,7 @@ export async function inspectDebugChannels(
|
|
|
2250
2250
|
if (bridge.plane === 'cloud' && !host) {
|
|
2251
2251
|
return (await inspectCloudDiagnostics(bridge)).availableChannels
|
|
2252
2252
|
}
|
|
2253
|
-
return bridge.send({ type: 'evaluate', code: '
|
|
2253
|
+
return bridge.send({ type: 'evaluate', code: 'globalThis.__sootsimDebug.channels()' })
|
|
2254
2254
|
}
|
|
2255
2255
|
|
|
2256
2256
|
// `debug find sheets|portals` — locate all live sheet / portal nodes.
|
|
@@ -2267,7 +2267,7 @@ export async function inspectDebugFind(
|
|
|
2267
2267
|
}
|
|
2268
2268
|
return bridge.send({
|
|
2269
2269
|
type: 'evaluate',
|
|
2270
|
-
code: `
|
|
2270
|
+
code: `globalThis.__sootsimTest.debugFind(${JSON.stringify(target)})`,
|
|
2271
2271
|
})
|
|
2272
2272
|
}
|
|
2273
2273
|
|
|
@@ -2286,7 +2286,7 @@ export async function callDebugBridge(
|
|
|
2286
2286
|
return bridge.send({
|
|
2287
2287
|
type: 'evaluate',
|
|
2288
2288
|
code: `(async () => {
|
|
2289
|
-
const result = await
|
|
2289
|
+
const result = await globalThis.__sootsimTest.evalInTenant(${JSON.stringify(code)})
|
|
2290
2290
|
if (!result.ok) throw new Error(result.error)
|
|
2291
2291
|
return result.value
|
|
2292
2292
|
})()`,
|
|
@@ -2450,17 +2450,17 @@ export async function inspectMemory(bridge: InspectBridge): Promise<MemoryReport
|
|
|
2450
2450
|
const result = (await bridge.send({
|
|
2451
2451
|
type: 'evaluate',
|
|
2452
2452
|
code: `(async () => {
|
|
2453
|
-
const host =
|
|
2453
|
+
const host = globalThis.__sootsimRenderHost
|
|
2454
2454
|
const stats = host?.queryStats ? await host.queryStats() : null
|
|
2455
|
-
const shellRaw =
|
|
2456
|
-
? await
|
|
2455
|
+
const shellRaw = globalThis.__sootsimShellMemory
|
|
2456
|
+
? await globalThis.__sootsimShellMemory()
|
|
2457
2457
|
: null
|
|
2458
2458
|
const shell = shellRaw && !shellRaw.error ? shellRaw : null
|
|
2459
2459
|
// the compositor paints home + app:one + app:two, so every app-surface
|
|
2460
2460
|
// picture and raster image is counted here and nowhere else.
|
|
2461
2461
|
let compositor = null
|
|
2462
2462
|
try {
|
|
2463
|
-
const cs = await
|
|
2463
|
+
const cs = await globalThis.__sootsimCompositor?.getStats?.(false, true)
|
|
2464
2464
|
compositor = cs?.memory ?? null
|
|
2465
2465
|
} catch {}
|
|
2466
2466
|
const normalize = (m) =>
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
export function buildGetNodeEval(matcher: string): string {
|
|
9
9
|
return `(async () => {
|
|
10
|
-
const t =
|
|
10
|
+
const t = globalThis.__sootsimTest
|
|
11
11
|
const q = ${JSON.stringify(matcher)}
|
|
12
12
|
let node = null
|
|
13
13
|
let via = null
|
|
@@ -30,7 +30,7 @@ export function buildGetNodeEval(matcher: string): string {
|
|
|
30
30
|
// parent chain — walk up from the node so the JSON dump is
|
|
31
31
|
// self-describing.
|
|
32
32
|
const parentChain = []
|
|
33
|
-
const root =
|
|
33
|
+
const root = globalThis.__sootsimRoot
|
|
34
34
|
if (root && typeof node.nodeId === 'number') {
|
|
35
35
|
const findPath = (n, targetId, path) => {
|
|
36
36
|
if (!n) return null
|
|
@@ -178,7 +178,7 @@ export async function waitForSimReady(
|
|
|
178
178
|
const count = await Promise.race([
|
|
179
179
|
bridge.send({
|
|
180
180
|
type: 'evaluate',
|
|
181
|
-
code: '(async () => (await
|
|
181
|
+
code: '(async () => (await globalThis.__sootsimTest?.getNodeCount()) ?? null)()',
|
|
182
182
|
}),
|
|
183
183
|
new Promise<never>((_, reject) => {
|
|
184
184
|
timer = setTimeout(
|
|
@@ -210,7 +210,7 @@ export async function waitForSimReady(
|
|
|
210
210
|
const observed = lastError
|
|
211
211
|
? `last bridge error: ${lastError}`
|
|
212
212
|
: lastCount === null
|
|
213
|
-
? 'guest never installed
|
|
213
|
+
? 'guest never installed globalThis.__sootsimTest'
|
|
214
214
|
: `last node count: ${String(lastCount)} (needs > ${minNodeCount})`
|
|
215
215
|
return {
|
|
216
216
|
bridge: null,
|
|
@@ -162,7 +162,7 @@ export async function runWaitEventSubcommand(opts: WaitEventOptions): Promise<vo
|
|
|
162
162
|
// but evaluate is the universally available shape and the cost
|
|
163
163
|
// of a string-baked function is negligible at 5Hz.
|
|
164
164
|
code: `(async () => {
|
|
165
|
-
const t =
|
|
165
|
+
const t = globalThis.SootSim?.bridges?.timeline
|
|
166
166
|
if (!t) return { ok: false, error: 'timeline bridge missing' }
|
|
167
167
|
return { ok: true, result: await t.recent(${JSON.stringify(query)}) }
|
|
168
168
|
})()`,
|