peachsim 0.1.571 → 0.1.573
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 +1 -1
- package/README.md +106 -106
- package/cli/app-config.ts +1 -1
- package/cli/app-fonts.ts +4 -4
- package/cli/auth.ts +11 -11
- package/cli/bin.ts +4 -4
- package/cli/bridge-flow-runner.ts +13 -13
- package/cli/browser-evals.ts +2 -2
- package/cli/cli-update.ts +6 -6
- package/cli/cloud-client.ts +16 -16
- package/cli/cloud-dispatch.ts +2 -2
- package/cli/cloud-session.ts +12 -12
- package/cli/cloud-test-tunnel.ts +4 -4
- package/cli/command-registry.ts +7 -7
- package/cli/commands/agent-wrapper.ts +7 -7
- package/cli/commands/agent.ts +16 -16
- package/cli/commands/app-fonts.ts +3 -3
- package/cli/commands/assert.ts +10 -10
- package/cli/commands/auth.ts +5 -5
- package/cli/commands/box/checkout-plane.ts +1 -1
- package/cli/commands/box/plane-share.ts +2 -2
- package/cli/commands/box/rnx-command.ts +5 -5
- package/cli/commands/box.ts +38 -38
- package/cli/commands/camera.ts +13 -13
- package/cli/commands/cleanup.ts +13 -13
- package/cli/commands/compat.ts +7 -7
- package/cli/commands/config.ts +5 -5
- package/cli/commands/control.ts +63 -63
- package/cli/commands/cpu-profile.ts +11 -11
- package/cli/commands/daemon-mac-app.ts +10 -10
- package/cli/commands/daemon.ts +29 -27
- package/cli/commands/debug.ts +35 -35
- package/cli/commands/desktop.ts +3 -3
- package/cli/commands/detox.ts +33 -33
- package/cli/commands/device.ts +9 -9
- package/cli/commands/diagnose.ts +17 -17
- package/cli/commands/do-chain.ts +4 -4
- package/cli/commands/electron.ts +9 -9
- package/cli/commands/film.ts +9 -9
- package/cli/commands/flow.ts +49 -49
- package/cli/commands/inspect/core.ts +12 -12
- package/cli/commands/inspect/count.ts +1 -1
- package/cli/commands/inspect/describe.ts +1 -1
- package/cli/commands/inspect/env.ts +2 -2
- package/cli/commands/inspect/find.ts +2 -2
- package/cli/commands/inspect/get-layout.ts +2 -2
- package/cli/commands/inspect/keyboard.ts +1 -1
- package/cli/commands/inspect/list.ts +4 -4
- package/cli/commands/inspect/memory.ts +1 -1
- package/cli/commands/inspect/resolve-target.ts +1 -1
- package/cli/commands/inspect/screens.ts +1 -1
- package/cli/commands/inspect/shared.ts +1 -1
- package/cli/commands/inspect/tree.ts +1 -1
- package/cli/commands/inspect/url.ts +1 -1
- package/cli/commands/inspect/wait-event.ts +5 -5
- package/cli/commands/inspect.ts +82 -82
- package/cli/commands/install-cli.ts +16 -16
- package/cli/commands/install-desktop.ts +26 -26
- package/cli/commands/login.ts +11 -11
- package/cli/commands/maestro-generate.ts +10 -10
- package/cli/commands/maestro.ts +77 -67
- package/cli/commands/mode.ts +4 -4
- package/cli/commands/no-bridge-hint.ts +12 -12
- package/cli/commands/perf.ts +11 -11
- package/cli/commands/permissions.ts +5 -5
- package/cli/commands/platform.ts +21 -21
- package/cli/commands/preview.ts +5 -5
- package/cli/commands/profile.ts +12 -12
- package/cli/commands/react.ts +15 -15
- package/cli/commands/record.ts +31 -31
- package/cli/commands/report-issue.ts +4 -4
- package/cli/commands/reset.ts +2 -2
- package/cli/commands/runtime.ts +23 -23
- package/cli/commands/screenshot-command.ts +2 -2
- package/cli/commands/screenshot-layers.ts +5 -5
- package/cli/commands/screenshot-mode.ts +7 -7
- package/cli/commands/screenshot.ts +24 -24
- package/cli/commands/screenshots-capture.ts +13 -13
- package/cli/commands/screenshots.ts +6 -6
- package/cli/commands/serve.ts +12 -12
- package/cli/commands/setup.ts +25 -25
- package/cli/commands/skills.ts +30 -23
- package/cli/commands/slides.ts +20 -20
- package/cli/commands/state.ts +2 -2
- package/cli/commands/storage.ts +3 -3
- package/cli/commands/telemetry.ts +2 -2
- package/cli/commands/test.ts +15 -15
- package/cli/commands/three-mode.ts +17 -17
- package/cli/commands/timeline.ts +12 -12
- package/cli/commands/upgrade.ts +11 -11
- package/cli/commands/upload.ts +26 -26
- package/cli/commands/version.ts +7 -7
- package/cli/commands/what-happened.ts +20 -20
- package/cli/current-sim.ts +3 -3
- package/cli/desktop-companion.ts +16 -16
- package/cli/drivers/electron.ts +4 -4
- package/cli/drivers/playwright-sim-host.ts +7 -7
- package/cli/drivers/playwright.ts +4 -4
- package/cli/drivers/registry.ts +1 -1
- package/cli/drivers/types.ts +5 -5
- package/cli/flow-export.ts +1 -1
- package/cli/flow-file.ts +5 -5
- package/cli/flow-session.ts +1 -1
- package/cli/help-core.ts +13 -13
- package/cli/hints.ts +14 -14
- package/cli/inspect-notice-state.ts +1 -1
- package/cli/internal-child.ts +2 -2
- package/cli/maestro-js.ts +4 -4
- package/cli/maestro-report.ts +1 -1
- package/cli/main.ts +14 -14
- package/cli/outbound-endpoints.ts +30 -30
- package/cli/parse-args.ts +7 -7
- package/cli/privacy.ts +1 -1
- package/cli/recording-access.ts +10 -10
- package/cli/resolve-assets.ts +2 -2
- package/cli/rnx-in-process.ts +5 -5
- package/cli/run-registry.ts +1 -1
- package/cli/run-rnx-core.ts +3 -3
- package/cli/run-rnx.ts +1 -1
- package/cli/runtime-notes.ts +1 -1
- package/cli/self-invocation.ts +1 -1
- package/cli/send-to-box.ts +1 -1
- package/cli/shell-init.ts +40 -40
- package/cli/ui.ts +1 -1
- package/cli/ws-bridge.ts +22 -22
- package/detox/config-loader.ts +1 -1
- package/detox/index.ts +28 -28
- package/detox/navigation.ts +2 -2
- package/dist-lib/agent-daemon-client.cjs +12 -12
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +2 -2
- package/dist-lib/agent-sessions.cjs +12 -12
- package/dist-lib/attached-projects.cjs +4 -4
- package/dist-lib/auth/shared-session.cjs +4 -4
- 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 +4 -4
- package/dist-lib/bridge-contract-input.cjs +1 -1
- package/dist-lib/bridge-contract-input.mjs +1 -1
- package/dist-lib/bridge-contract.cjs +2 -2
- package/dist-lib/bridge-contract.mjs +2 -2
- package/dist-lib/capture-contract.cjs +1 -1
- package/dist-lib/capture-contract.mjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/cloud-contract.cjs +1 -1
- package/dist-lib/cloud-contract.mjs +1 -1
- package/dist-lib/cloud-test-args.cjs +1 -1
- package/dist-lib/cloud-test-args.mjs +1 -1
- package/dist-lib/cloud.cjs +42 -42
- package/dist-lib/cloud.mjs +42 -42
- package/dist-lib/config.cjs +2 -2
- package/dist-lib/detox/index.cjs +29 -29
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +12 -12
- package/dist-lib/host/bridge-host.cjs +72 -71
- 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 +6 -6
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +48 -48
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/menu.cjs +5 -5
- package/dist-lib/menu.mjs +5 -5
- 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 +15 -15
- package/dist-lib/profiles.cjs +4 -4
- package/dist-lib/public-brand.cjs +3 -3
- package/dist-lib/react-native-host-modules.cjs +1 -1
- package/dist-lib/react-native-host-modules.mjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +2 -1
- package/dist-lib/sdk.cjs +9 -9
- package/dist-lib/sdk.mjs +9 -9
- package/dist-lib/skills.cjs +416 -415
- package/dist-lib/swift-compile.cjs +1 -1
- package/dist-lib/swift-compile.mjs +1 -1
- 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.cjs +1 -1
- package/dist-lib/vite.cjs +24 -24
- package/package.json +1 -1
- package/scripts/dev-server-scanner.ts +4 -3
- package/skills/contrast/SKILL.md +75 -75
- package/skills/{rnx-debug → peach-debug}/SKILL.md +90 -90
- package/skills/{rnx-perf → peach-perf}/SKILL.md +13 -13
- package/skills/{rnx-setup → peach-setup}/SKILL.md +60 -60
- package/skills/{rnx-test → peach-test}/SKILL.md +44 -44
- package/skills/{rnx-visual → peach-visual}/SKILL.md +26 -26
- package/src/agent-daemon-client.ts +5 -5
- package/src/agent-events.ts +1 -1
- package/src/agent-identity.ts +1 -1
- package/src/agent-sessions.ts +13 -13
- package/src/attached-projects.ts +1 -1
- package/src/auth/shared-session.ts +1 -1
- package/src/bridge-constants.ts +3 -3
- package/src/bridge-contract-input.ts +1 -1
- package/src/bridge-contract.ts +3 -3
- package/src/cli-version.ts +6 -6
- package/src/cloud.ts +40 -40
- package/src/config.ts +1 -1
- package/src/connect.ts +6 -6
- package/src/dev-server-open.ts +8 -8
- package/src/disk-cleanup.ts +3 -3
- package/src/home-paths.ts +26 -26
- package/src/host/agent-host.ts +3 -3
- package/src/host/bridge-host.ts +33 -33
- package/src/host/fetch-proxy-handler.ts +1 -1
- package/src/host/plane-host.ts +2 -2
- package/src/host/replacement-module-handler.ts +2 -2
- package/src/menu.ts +2 -2
- package/src/metro-plugin.ts +7 -7
- package/src/metro-production-bundle.ts +2 -2
- package/src/native-dev-bundle-url.ts +2 -2
- package/src/playwright-host-log.ts +1 -1
- package/src/public-brand.ts +2 -2
- package/src/react-native-host-modules.ts +1 -1
- package/src/rolldown-plugin-swift.ts +3 -3
- package/src/runtime-assets.ts +11 -11
- package/src/runtime-delivery.ts +6 -6
- package/src/screenshots/orchestrate.ts +1 -1
- package/src/screenshots/org-deck.ts +1 -1
- package/src/screenshots/schema.ts +2 -2
- package/src/sim-client.ts +1 -1
- package/src/skills/builtin/compat-check.ts +2 -2
- package/src/vite-plugin-one.ts +8 -8
- package/src/vite-plugin-swift.ts +3 -3
- package/src/vite-plugin.ts +6 -19
package/src/host/bridge-host.ts
CHANGED
|
@@ -234,13 +234,13 @@ export interface BridgeHostOptions {
|
|
|
234
234
|
/** try preferred port, then port+1, port+2, …, up to this many attempts
|
|
235
235
|
* before giving up. defaults to 10. set 1 to disable fallback. */
|
|
236
236
|
portFallbackCount?: number
|
|
237
|
-
/** when true, write ~/.
|
|
237
|
+
/** when true, write ~/.peach/daemon.json on successful bind + update
|
|
238
238
|
* it on a heartbeat interval + remove it on close. only the standalone
|
|
239
|
-
* `
|
|
239
|
+
* `peach serve` process should set this — tests, vite plugin, and
|
|
240
240
|
* anything embedded should leave it off to avoid clobbering a real
|
|
241
241
|
* daemon's lockfile. defaults to false. */
|
|
242
242
|
writeLockfile?: boolean
|
|
243
|
-
/** when true, write an owner-scoped record under ~/.
|
|
243
|
+
/** when true, write an owner-scoped record under ~/.peach/dev-bridges on
|
|
244
244
|
* successful bind, update it on a heartbeat interval, and remove only that
|
|
245
245
|
* record on close. the Vite dev shell sets this so local CLI commands can
|
|
246
246
|
* address every live source bridge without concurrent worktrees replacing
|
|
@@ -257,7 +257,7 @@ export interface BridgeHostOptions {
|
|
|
257
257
|
* resolves the daemon's own loopback host (localhost:<runtimePort>) to
|
|
258
258
|
* the dev `contrast.localhost:3000` stack, so a *prod* CLI user's preview
|
|
259
259
|
* recording would upload to a localhost stack that doesn't exist. the
|
|
260
|
-
* `
|
|
260
|
+
* `peach serve` command resolves this with the same probe the
|
|
261
261
|
* upload itself uses (`resolveDefaultUploadOrigin`). */
|
|
262
262
|
contrastOrigin?: string
|
|
263
263
|
/** override the abandoned-sim GC TTL (ms). defaults to
|
|
@@ -311,7 +311,7 @@ const HTTP_MIME_TYPES: Record<string, string> = {
|
|
|
311
311
|
'.mov': 'video/quicktime',
|
|
312
312
|
}
|
|
313
313
|
|
|
314
|
-
// `
|
|
314
|
+
// `peach camera play` stages a video under ~/.peach/camera-fixtures and the
|
|
315
315
|
// simulator plays it as the camera feed. the route below serves that one
|
|
316
316
|
// directory, addressed by basename only.
|
|
317
317
|
const CAMERA_FIXTURE_ROUTE = '/__camera-fixtures/'
|
|
@@ -321,7 +321,7 @@ const CAMERA_FIXTURE_ROUTE = '/__camera-fixtures/'
|
|
|
321
321
|
const CAMERA_FIXTURE_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/
|
|
322
322
|
|
|
323
323
|
/** inject host-provided globals into the served runtime html:
|
|
324
|
-
* - `window.__sootsimSharedConfig` — parsed `~/.
|
|
324
|
+
* - `window.__sootsimSharedConfig` — parsed `~/.peach/config.json`,
|
|
325
325
|
* read during engine settingsStore module init (see
|
|
326
326
|
* settings/persistence.ts). mirrors the inject-into-html plugin in the
|
|
327
327
|
* shell vite dev server so dev and prod surfaces both produce it.
|
|
@@ -333,7 +333,7 @@ const CAMERA_FIXTURE_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/
|
|
|
333
333
|
* the same server on the same port, but a daemon whose preferred 7668
|
|
334
334
|
* was taken falls back to 7669+. without this the runtime page would
|
|
335
335
|
* hardcode the 7668 default in `resolveBridgePort` and register on a
|
|
336
|
-
* *different* daemon (or none), so `
|
|
336
|
+
* *different* daemon (or none), so `peach open` times out waiting for
|
|
337
337
|
* a sim that connected to the wrong bridge.
|
|
338
338
|
* - `window.__sootsimContrastOrigin` — the contrast origin for auth /
|
|
339
339
|
* billing / preview uploads. the daemon serves runtimes from its own
|
|
@@ -408,8 +408,8 @@ export class SootSimBridgeHost {
|
|
|
408
408
|
private static USER_BOOT_LEASE_TTL_MS = 60_000
|
|
409
409
|
private static SIM_RECONNECT_TTL_MS = 30_000
|
|
410
410
|
// abandoned-tab GC. the ws heartbeat only reaps sims whose socket went
|
|
411
|
-
// dead — but a background tab from a prior `
|
|
412
|
-
// keeps its socket alive (the page still pongs) forever, so `
|
|
411
|
+
// dead — but a background tab from a prior `peach open` / QA / test run
|
|
412
|
+
// keeps its socket alive (the page still pongs) forever, so `peach list`
|
|
413
413
|
// accretes dozens of zombie sims that all time out on every command (QA
|
|
414
414
|
// F21-3, carried F19-2). reap a sim only when it is provably nobody's:
|
|
415
415
|
// not primary, not user-focused, no CLI attached, no active lease, and no
|
|
@@ -417,7 +417,7 @@ export class SootSimBridgeHost {
|
|
|
417
417
|
// terminal 4001 code, so the client closes the abandoned window instead
|
|
418
418
|
// of reconnecting the zombie straight back in.
|
|
419
419
|
private static SIM_IDLE_REAP_TTL_MS = 30 * 60_000
|
|
420
|
-
// automation sims (spawned by the playwright driver: `
|
|
420
|
+
// automation sims (spawned by the playwright driver: `peach open --driver
|
|
421
421
|
// playwright`, the factory/screenshot capture path — `meta.sootsimHostDriver
|
|
422
422
|
// === 'playwright'`) are unattended one-shot browsers, never a human's tab. a
|
|
423
423
|
// capture run opens one per slide/app/retry and the 30-min human/dev TTL lets
|
|
@@ -448,7 +448,7 @@ export class SootSimBridgeHost {
|
|
|
448
448
|
// dropped, sim crashed) leave their server-side WebSocket sitting "open"
|
|
449
449
|
// forever. ping every WS_HEARTBEAT_INTERVAL_MS; if the previous round's
|
|
450
450
|
// ping was never answered, terminate(). that fires 'close' which runs the
|
|
451
|
-
// sim-cleanup path and stops `
|
|
451
|
+
// sim-cleanup path and stops `peach list` from showing 8 zombie
|
|
452
452
|
// sims that all time out on every command.
|
|
453
453
|
private wsHeartbeatTimer: NodeJS.Timeout | null = null
|
|
454
454
|
private wsIsAlive = new WeakMap<WebSocket, boolean>()
|
|
@@ -470,7 +470,7 @@ export class SootSimBridgeHost {
|
|
|
470
470
|
constructor(opts: BridgeHostOptions = {}) {
|
|
471
471
|
this.preferredPort = opts.port ?? DEFAULT_SOOTSIM_BRIDGE_PORT
|
|
472
472
|
this.port = this.preferredPort
|
|
473
|
-
// default off — callers that want the lockfile (
|
|
473
|
+
// default off — callers that want the lockfile (peach serve) opt in.
|
|
474
474
|
this.shouldWriteLockfile = opts.writeLockfile === true
|
|
475
475
|
this.shouldWriteDevLockfile = opts.writeDevLockfile === true
|
|
476
476
|
this.getShellPort = opts.getShellPort ?? null
|
|
@@ -676,7 +676,7 @@ export class SootSimBridgeHost {
|
|
|
676
676
|
if (!msg || typeof msg !== 'object') return
|
|
677
677
|
|
|
678
678
|
// agent:* messages are routed uniformly regardless of socket role.
|
|
679
|
-
// CLI (`
|
|
679
|
+
// CLI (`peach agent …`), electron main (daemon client), and
|
|
680
680
|
// sim shells all use the same envelope, and agent event
|
|
681
681
|
// subscriptions work from any of them — this is the whole point of
|
|
682
682
|
// moving session ownership into the daemon.
|
|
@@ -687,7 +687,7 @@ export class SootSimBridgeHost {
|
|
|
687
687
|
|
|
688
688
|
// plane:* is the project file plane, routed the same way and for the
|
|
689
689
|
// same reason: the CLI, a box, and a browser tab all speak one
|
|
690
|
-
// envelope. see plans/
|
|
690
|
+
// envelope. see plans/peach-cloud/transport-decision.md.
|
|
691
691
|
if (typeof msg.type === 'string' && msg.type.startsWith('plane:')) {
|
|
692
692
|
void this.planeHost.handleMessage(ws, msg)
|
|
693
693
|
return
|
|
@@ -822,7 +822,7 @@ export class SootSimBridgeHost {
|
|
|
822
822
|
return
|
|
823
823
|
}
|
|
824
824
|
|
|
825
|
-
// write a partial patch into ~/.
|
|
825
|
+
// write a partial patch into ~/.peach/config.json. fired by the
|
|
826
826
|
// engine's settingsStore when a persisted key flips in a browser
|
|
827
827
|
// tab (which has no fs access of its own). after the merge, we
|
|
828
828
|
// broadcast the new full snapshot to every connected sim so any
|
|
@@ -891,7 +891,7 @@ export class SootSimBridgeHost {
|
|
|
891
891
|
expiresAt: Date.now() + SootSimBridgeHost.USER_BOOT_LEASE_TTL_MS,
|
|
892
892
|
}
|
|
893
893
|
process.stderr.write(
|
|
894
|
-
`
|
|
894
|
+
`peach booted ${booted.length} cli client(s)${hadLease ? ' (overrode prior lease)' : ''}; held sim for user [${sim.id}]\n`,
|
|
895
895
|
)
|
|
896
896
|
this.recordSimAction(sim.id, 'sim booted cli clients')
|
|
897
897
|
this.broadcastSimClientStates()
|
|
@@ -1029,7 +1029,7 @@ export class SootSimBridgeHost {
|
|
|
1029
1029
|
ws.send(
|
|
1030
1030
|
JSON.stringify({
|
|
1031
1031
|
id: msg.id,
|
|
1032
|
-
error: `sim ${targetSim.id} is locked by another cli — use \`
|
|
1032
|
+
error: `sim ${targetSim.id} is locked by another cli — use \`peach claim ${targetSim.id} --force\` or \`peach open --new\``,
|
|
1033
1033
|
_locked: outcome.lock,
|
|
1034
1034
|
}),
|
|
1035
1035
|
)
|
|
@@ -1161,7 +1161,7 @@ export class SootSimBridgeHost {
|
|
|
1161
1161
|
const claimed = claimDaemonLockfile(this.buildLockfileSnapshot())
|
|
1162
1162
|
if (!claimed) {
|
|
1163
1163
|
throw new Error(
|
|
1164
|
-
'another
|
|
1164
|
+
'another peach daemon wrote the lockfile during startup — aborting',
|
|
1165
1165
|
)
|
|
1166
1166
|
}
|
|
1167
1167
|
} catch (err) {
|
|
@@ -1291,7 +1291,7 @@ export class SootSimBridgeHost {
|
|
|
1291
1291
|
})
|
|
1292
1292
|
.catch((err: unknown) => {
|
|
1293
1293
|
const message = err instanceof Error ? err.message : String(err)
|
|
1294
|
-
console.error('[
|
|
1294
|
+
console.error('[peach] /__server-scan failed:', message)
|
|
1295
1295
|
return this.scanCache ?? []
|
|
1296
1296
|
})
|
|
1297
1297
|
.finally(() => {
|
|
@@ -1301,7 +1301,7 @@ export class SootSimBridgeHost {
|
|
|
1301
1301
|
}
|
|
1302
1302
|
|
|
1303
1303
|
// serves one staged camera fixture. addressed by basename inside
|
|
1304
|
-
// ~/.
|
|
1304
|
+
// ~/.peach/camera-fixtures, never by a caller-supplied path, so there is
|
|
1305
1305
|
// no traversal surface to defend: a name that is not a plain basename is
|
|
1306
1306
|
// rejected outright. range support is not optional here — chrome asks for
|
|
1307
1307
|
// byte ranges on media and cannot seek or loop a fixture without it.
|
|
@@ -1426,13 +1426,13 @@ export class SootSimBridgeHost {
|
|
|
1426
1426
|
if (this.httpServer) this.writeLockfileSnapshot()
|
|
1427
1427
|
return
|
|
1428
1428
|
}
|
|
1429
|
-
// an isolated dev daemon (explicit
|
|
1429
|
+
// an isolated dev daemon (explicit PEACH_HOME, dev checkout, nothing
|
|
1430
1430
|
// staged) serves the repo's public/sootsim build. auto-installing the
|
|
1431
1431
|
// published runtime here would stage it active and shadow that dev build
|
|
1432
1432
|
// (runtime-assets prefers a staged runtime under an explicit home), so the
|
|
1433
1433
|
// daemon would silently validate published code instead of the checkout.
|
|
1434
1434
|
// local-publish writes the marker above when it stages a source build.
|
|
1435
|
-
if (process.env.
|
|
1435
|
+
if (process.env.PEACH_HOME && isSootsimDevCheckout() && !readActiveRuntime()) {
|
|
1436
1436
|
return
|
|
1437
1437
|
}
|
|
1438
1438
|
void this.runRuntimeUpdate('startup')
|
|
@@ -1448,7 +1448,7 @@ export class SootSimBridgeHost {
|
|
|
1448
1448
|
this.runtimeUpdateInFlight = (async () => {
|
|
1449
1449
|
try {
|
|
1450
1450
|
if (reason === 'startup') {
|
|
1451
|
-
process.stderr.write('
|
|
1451
|
+
process.stderr.write('peach: checking for runtime updates…\n')
|
|
1452
1452
|
}
|
|
1453
1453
|
const result = await rnxRuntime.updateToLatest({
|
|
1454
1454
|
protectVersions: this.connectedRuntimeVersions(),
|
|
@@ -1456,14 +1456,14 @@ export class SootSimBridgeHost {
|
|
|
1456
1456
|
if (!result.updated || !result.latestVersion) {
|
|
1457
1457
|
if (reason === 'startup') {
|
|
1458
1458
|
process.stderr.write(
|
|
1459
|
-
`
|
|
1459
|
+
`peach: runtime ${this.activeRuntimeVersion ?? '(none)'} is current\n`,
|
|
1460
1460
|
)
|
|
1461
1461
|
}
|
|
1462
1462
|
return
|
|
1463
1463
|
}
|
|
1464
1464
|
const previousVersion = this.activeRuntimeVersion
|
|
1465
1465
|
const active = this.setActiveRuntime(result.latestVersion)
|
|
1466
|
-
process.stderr.write(`
|
|
1466
|
+
process.stderr.write(`peach runtime updated to ${active.version} (${reason})\n`)
|
|
1467
1467
|
// the daemon's stderr goes to a log nobody watches — drop a one-shot
|
|
1468
1468
|
// notice so the next interactive CLI run tells the user their engine
|
|
1469
1469
|
// moved (consumed + deleted by bin.ts).
|
|
@@ -1476,7 +1476,7 @@ export class SootSimBridgeHost {
|
|
|
1476
1476
|
} catch {}
|
|
1477
1477
|
} catch (err) {
|
|
1478
1478
|
process.stderr.write(
|
|
1479
|
-
`
|
|
1479
|
+
`peach runtime update failed (${reason}): ${
|
|
1480
1480
|
err instanceof Error ? err.message : String(err)
|
|
1481
1481
|
}\n`,
|
|
1482
1482
|
)
|
|
@@ -1493,7 +1493,7 @@ export class SootSimBridgeHost {
|
|
|
1493
1493
|
this.writeLockfileSnapshot()
|
|
1494
1494
|
} catch {}
|
|
1495
1495
|
}
|
|
1496
|
-
process.stderr.write('
|
|
1496
|
+
process.stderr.write('peach: ready\n')
|
|
1497
1497
|
}
|
|
1498
1498
|
}
|
|
1499
1499
|
})()
|
|
@@ -1738,7 +1738,7 @@ export class SootSimBridgeHost {
|
|
|
1738
1738
|
return
|
|
1739
1739
|
}
|
|
1740
1740
|
|
|
1741
|
-
// /__camera-fixtures/<name> — the staged video behind `
|
|
1741
|
+
// /__camera-fixtures/<name> — the staged video behind `peach camera play`.
|
|
1742
1742
|
// the shell page is a different origin from this daemon (vite dev on 5173,
|
|
1743
1743
|
// daemon on 7668+), and the camera pipeline draws the <video> to a canvas
|
|
1744
1744
|
// and reads it back, so this needs real CORS or the canvas taints and
|
|
@@ -1816,8 +1816,8 @@ export class SootSimBridgeHost {
|
|
|
1816
1816
|
res.writeHead(503, { 'Content-Type': 'text/plain; charset=utf-8' })
|
|
1817
1817
|
res.end(
|
|
1818
1818
|
versionedRuntimeRequest
|
|
1819
|
-
? `
|
|
1820
|
-
: '
|
|
1819
|
+
? `peach: runtime ${requestedRuntime ?? '(invalid version origin)'} is not installed. run \`peach open\` from that app again.`
|
|
1820
|
+
: 'peach: no active runtime installed. run `peach runtime install` to fetch one.',
|
|
1821
1821
|
)
|
|
1822
1822
|
return
|
|
1823
1823
|
}
|
|
@@ -2012,7 +2012,7 @@ export class SootSimBridgeHost {
|
|
|
2012
2012
|
this.reapIdleSims(now)
|
|
2013
2013
|
}
|
|
2014
2014
|
|
|
2015
|
-
// GC abandoned sims so `
|
|
2015
|
+
// GC abandoned sims so `peach list` stays usable across long dev / QA /
|
|
2016
2016
|
// test sessions (F21-3). conservative on purpose: a sim is only reaped
|
|
2017
2017
|
// when every "someone cares about this" signal is absent.
|
|
2018
2018
|
//
|
|
@@ -2028,7 +2028,7 @@ export class SootSimBridgeHost {
|
|
|
2028
2028
|
// using is the primary and/or holds a fresh user-active lease; one that is
|
|
2029
2029
|
// none of those and idle past the TTL is abandoned regardless of a stale
|
|
2030
2030
|
// focus flag.
|
|
2031
|
-
// automation sims are spawned by the playwright driver (`
|
|
2031
|
+
// automation sims are spawned by the playwright driver (`peach open
|
|
2032
2032
|
// --driver playwright`, the factory/screenshot capture path), which tags them
|
|
2033
2033
|
// with `meta.sootsimHostDriver === 'playwright'` via the host's addInitScript.
|
|
2034
2034
|
// they are unattended one-shot browsers, never a human's tab, so they get a
|
|
@@ -2527,7 +2527,7 @@ export class SootSimBridgeHost {
|
|
|
2527
2527
|
if (candidates.length > 1) {
|
|
2528
2528
|
throw new Error(
|
|
2529
2529
|
`multiple sims are connected: ${candidates.map((sim) => sim.id).join(', ')}; ` +
|
|
2530
|
-
'run `
|
|
2530
|
+
'run `peach use <sim>` or pass `--sim <sim>`',
|
|
2531
2531
|
)
|
|
2532
2532
|
}
|
|
2533
2533
|
const candidate = candidates[0]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// shared fetch-proxy + app-api handlers for the
|
|
1
|
+
// shared fetch-proxy + app-api handlers for the peach dev/daemon HTTP
|
|
2
2
|
// surface. both the vite dev middleware (packages/peach-shell/src/
|
|
3
3
|
// dev-middleware.ts) and the daemon bridge (packages/peachsim/src/host/
|
|
4
4
|
// bridge-host.ts) mount these on their respective servers so guest bundle
|
package/src/host/plane-host.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// `plane:*` — the project file plane over the loopback bridge, so a browser
|
|
2
2
|
// tab can reach a real local box. the envelope and its constraints are decided
|
|
3
|
-
// in plans/
|
|
3
|
+
// in plans/peach-cloud/transport-decision.md; this is the local half.
|
|
4
4
|
//
|
|
5
5
|
// the vocabulary is exactly ProjectFilePlane's members, because the point is
|
|
6
6
|
// that a remote plane is a third provider behind that seam rather than a
|
|
@@ -124,7 +124,7 @@ export class PlaneHost {
|
|
|
124
124
|
const root = this.realRoot(String(msg.root ?? ''))
|
|
125
125
|
if (!this.registered.has(root)) {
|
|
126
126
|
throw new PlaneNotRegisteredError(
|
|
127
|
-
`no box has registered ${root}; start one with \`
|
|
127
|
+
`no box has registered ${root}; start one with \`peach box\` there`,
|
|
128
128
|
)
|
|
129
129
|
}
|
|
130
130
|
const existingId = this.byRoot.get(root)
|
|
@@ -36,7 +36,7 @@ function sendJavaScript(req: IncomingMessage, res: ServerResponse, source: strin
|
|
|
36
36
|
export function isReplacementModuleRequestUrl(rawUrl?: string): boolean {
|
|
37
37
|
if (!rawUrl) return false
|
|
38
38
|
try {
|
|
39
|
-
const pathname = new URL(rawUrl, 'http://
|
|
39
|
+
const pathname = new URL(rawUrl, 'http://peach.local').pathname
|
|
40
40
|
return pathname === REPLACEMENT_MODULE_ROUTE
|
|
41
41
|
} catch {
|
|
42
42
|
return false
|
|
@@ -51,7 +51,7 @@ export async function handleReplacementModuleRequest(
|
|
|
51
51
|
const rawUrl = req.url || ''
|
|
52
52
|
let url: URL
|
|
53
53
|
try {
|
|
54
|
-
url = new URL(rawUrl, 'http://
|
|
54
|
+
url = new URL(rawUrl, 'http://peach.local')
|
|
55
55
|
} catch {
|
|
56
56
|
return false
|
|
57
57
|
}
|
package/src/menu.ts
CHANGED
|
@@ -196,7 +196,7 @@ function appMenu(): SootSimMenuDef {
|
|
|
196
196
|
},
|
|
197
197
|
{ type: 'separator' },
|
|
198
198
|
{
|
|
199
|
-
label:
|
|
199
|
+
label: `Hide ${rnxPublicBrand.name}`,
|
|
200
200
|
accelerator: 'CmdOrCtrl+H',
|
|
201
201
|
action: 'hide',
|
|
202
202
|
hiddenIn: 'browser',
|
|
@@ -210,7 +210,7 @@ function appMenu(): SootSimMenuDef {
|
|
|
210
210
|
{ label: 'Show All', action: 'unhide', hiddenIn: 'browser' },
|
|
211
211
|
{ type: 'separator' },
|
|
212
212
|
{
|
|
213
|
-
label:
|
|
213
|
+
label: `Quit ${rnxPublicBrand.name}`,
|
|
214
214
|
accelerator: 'CmdOrCtrl+Q',
|
|
215
215
|
action: 'quit',
|
|
216
216
|
hiddenIn: 'browser',
|
package/src/metro-plugin.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
//
|
|
2
|
-
// shell assets come from an engine runtime under ~/.
|
|
3
|
-
// by `
|
|
1
|
+
// peach metro plugin for dev shell and bundle module identity annotation.
|
|
2
|
+
// shell assets come from an engine runtime under ~/.peach/runtimes/, fetched
|
|
3
|
+
// by `peach runtime install`. ordinary localhost requests
|
|
4
4
|
// follow active; a version-owned localhost origin stays on its exact directory
|
|
5
5
|
// when active changes, so one loaded shell cannot mix runtime chunk trees.
|
|
6
6
|
//
|
|
@@ -121,7 +121,7 @@ function createMetroDefaultSerializer(projectRoot: string): MetroSerializer {
|
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
// the only thing
|
|
124
|
+
// the only thing peach adds to an ordinary Metro bundle. production needs the
|
|
125
125
|
// footer because Metro drops the fourth `__d` argument when `dev` is false;
|
|
126
126
|
// development keeps that verbose name and receives the same identity without
|
|
127
127
|
// changing resolution, transforms, or the trailing source map.
|
|
@@ -231,7 +231,7 @@ export function withRNX<T extends Record<string, unknown>>(config: T): T {
|
|
|
231
231
|
try {
|
|
232
232
|
connect = require('connect')
|
|
233
233
|
} catch {
|
|
234
|
-
console.warn('[
|
|
234
|
+
console.warn('[peach] connect not available')
|
|
235
235
|
return middleware
|
|
236
236
|
}
|
|
237
237
|
|
|
@@ -313,7 +313,7 @@ export function withRNX<T extends Record<string, unknown>>(config: T): T {
|
|
|
313
313
|
|
|
314
314
|
server.use(middleware)
|
|
315
315
|
|
|
316
|
-
console.log(`[
|
|
316
|
+
console.log(`[peach] serving at ${prefix}/`)
|
|
317
317
|
return server
|
|
318
318
|
},
|
|
319
319
|
}
|
|
@@ -333,7 +333,7 @@ function resolveMetroPort(server: MetroConfigWithServer['server']): number {
|
|
|
333
333
|
inlinePort || splitPort || process.env.RCT_METRO_PORT || server?.port || 8081
|
|
334
334
|
const port = Number(rawPort)
|
|
335
335
|
if (!Number.isInteger(port) || port <= 0) {
|
|
336
|
-
throw new Error(`
|
|
336
|
+
throw new Error(`peach: Metro port must be a positive integer, got ${rawPort}`)
|
|
337
337
|
}
|
|
338
338
|
return port
|
|
339
339
|
}
|
|
@@ -24,7 +24,7 @@ export interface RNXMetroModuleIdentity extends RNXMetroModuleIdentityMetadata {
|
|
|
24
24
|
sourceMappingUrl: string | null
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
// the production bundle
|
|
27
|
+
// the production bundle peach loads is the app's ORDINARY production bundle.
|
|
28
28
|
// nothing about resolution changes, so these are plain Metro production
|
|
29
29
|
// options and the artifact is byte-identical to what the app ships apart
|
|
30
30
|
// from the identity footer the plugin's serializer appends.
|
|
@@ -214,7 +214,7 @@ export function readRNXMetroModuleIdentity(
|
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
// the exact layout Metro's baseJSBundle emits and the
|
|
217
|
+
// the exact layout Metro's baseJSBundle emits and the peach runtime contract
|
|
218
218
|
// depends on: a prelude, then one `__d(` or `__r(` statement per line, each
|
|
219
219
|
// running until the next statement starts its own line. one reader owns this
|
|
220
220
|
// recognition so the loader's identity validation, the source-map attribution
|
|
@@ -42,7 +42,7 @@ export function alignLoopbackBundleUrlWithProbe(
|
|
|
42
42
|
// unreliably on small CI runners (tens of seconds when metro is warm,
|
|
43
43
|
// minutes cold, sometimes past any wait-ready budget). a minified bundle
|
|
44
44
|
// parses/executes far faster and reboots reliably. gated on
|
|
45
|
-
// SOOTSIM_PREVIEW_PROD_BUNDLE so normal interactive `
|
|
45
|
+
// SOOTSIM_PREVIEW_PROD_BUNDLE so normal interactive `peach open` keeps
|
|
46
46
|
// dev=true. app-agnostic: rewrites whatever metro/launchAsset advertised.
|
|
47
47
|
function applyPreviewProdBundle(parsed: URL): void {
|
|
48
48
|
if (!process.env.SOOTSIM_PREVIEW_PROD_BUNDLE) return
|
|
@@ -95,7 +95,7 @@ export function normalizeNativeDevBundleUrl(bundleUrl: string): string {
|
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
// explicit override used by `
|
|
98
|
+
// explicit override used by `peach open` to flip metro's `hot` query when
|
|
99
99
|
// the caller knows their context: interactive opens want `hot=true` so metro
|
|
100
100
|
// includes its HMR/react-refresh runtime in the bundle prelude and pushes
|
|
101
101
|
// edits as `update` events; `--driver playwright` / agent-test runs want
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// (sootsim- -> rnx-) without the recorder following, which silently failed
|
|
6
6
|
// every hosted job with "run completed without hardware WebGL proof" even when
|
|
7
7
|
// the preview itself uploaded fine.
|
|
8
|
-
export const PLAYWRIGHT_HOST_LOG_PREFIX = '
|
|
8
|
+
export const PLAYWRIGHT_HOST_LOG_PREFIX = 'peach-playwright-host-'
|
|
9
9
|
|
|
10
10
|
export function playwrightHostLogName(nowMs: number, pid: number): string {
|
|
11
11
|
return `${PLAYWRIGHT_HOST_LOG_PREFIX}${nowMs.toString(36)}-${pid}.log`
|
package/src/public-brand.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* react-native specifiers whose upstream JavaScript must stay in a guest bundle.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* peach owns the rest of the react-native package through its host-module registry.
|
|
5
5
|
* these modules instead run against globals installed by the simulator, which
|
|
6
6
|
* preserves upstream platform, style, event-emitter, and TurboModule behavior.
|
|
7
7
|
*/
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
//
|
|
32
32
|
// no babel anywhere in this path: resolveId and load only, emitting an ESM
|
|
33
33
|
// module. offline `one dev` fails loud at the submit, the same as a browser
|
|
34
|
-
// build without a credential; the standalone `
|
|
34
|
+
// build without a credential; the standalone `peach` CLI keeps the local
|
|
35
35
|
// toolchain plugin for that case.
|
|
36
36
|
|
|
37
37
|
import fs from 'node:fs'
|
|
@@ -46,7 +46,7 @@ import { entryRootId } from './vite-plugin-swift'
|
|
|
46
46
|
import type { SwiftModuleAddress } from './swift-submit'
|
|
47
47
|
import type { Plugin } from 'vite'
|
|
48
48
|
|
|
49
|
-
const VIRTUAL_PREFIX = '\
|
|
49
|
+
const VIRTUAL_PREFIX = '\0peach-swift-remote:'
|
|
50
50
|
|
|
51
51
|
export interface SwiftRemotePluginOptions {
|
|
52
52
|
/** origin serving `/api/swift-compile` (the Contrast app). */
|
|
@@ -189,7 +189,7 @@ export function swiftRemotePlugin(options: SwiftRemotePluginOptions): Plugin {
|
|
|
189
189
|
)
|
|
190
190
|
}
|
|
191
191
|
return {
|
|
192
|
-
name: '
|
|
192
|
+
name: 'peach-swift-remote',
|
|
193
193
|
enforce: 'pre',
|
|
194
194
|
|
|
195
195
|
async resolveId(source, importer) {
|
package/src/runtime-assets.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// helpers for serving the installed sootsim engine runtime from framework
|
|
2
|
-
// dev servers. the runtime is managed by `
|
|
3
|
-
// under ~/.
|
|
2
|
+
// dev servers. the runtime is managed by `peach runtime install` and lives
|
|
3
|
+
// under ~/.peach/runtimes/<version>.
|
|
4
4
|
|
|
5
5
|
import fs from 'fs'
|
|
6
6
|
import path from 'path'
|
|
@@ -9,7 +9,7 @@ import { isValidRuntimeVersion } from '@contrast/runtime-delivery'
|
|
|
9
9
|
import { readActiveRuntime, runtimeDir } from './home-paths.ts'
|
|
10
10
|
|
|
11
11
|
export const SOOTSIM_RUNTIME_MISSING_MESSAGE =
|
|
12
|
-
'[
|
|
12
|
+
'[peach] no engine runtime installed. run `peach runtime install`'
|
|
13
13
|
|
|
14
14
|
// --- dev-checkout mode boundary --------------------------------------------
|
|
15
15
|
//
|
|
@@ -20,13 +20,13 @@ export const SOOTSIM_RUNTIME_MISSING_MESSAGE =
|
|
|
20
20
|
// boundary, not a preference or a runtime fallback chain — the check is
|
|
21
21
|
// structural (the monorepo layout is present next to this module) and
|
|
22
22
|
// deterministic (the dev build's files exist). it exists because the daemon and
|
|
23
|
-
// the /__soot plugin otherwise serve ~/.
|
|
23
|
+
// the /__soot plugin otherwise serve ~/.peach/runtimes/<active>, a PUBLISHED
|
|
24
24
|
// runtime that `bun dev` never refreshes, so local engine edits are invisible
|
|
25
25
|
// until a manual publish — the silent trap that cost a full night of
|
|
26
26
|
// already-fixed bugs re-reproducing.
|
|
27
27
|
//
|
|
28
28
|
// the isolated CI headless path (scripts/local-publish-runtime.sh) sets
|
|
29
|
-
//
|
|
29
|
+
// PEACH_HOME to a dedicated dir precisely to validate the published-runtime
|
|
30
30
|
// code path; keying off that EXISTING isolation env keeps it (and packaged
|
|
31
31
|
// electron with a custom home) on the installed runtime.
|
|
32
32
|
let _monorepoRootCache: string | null | undefined
|
|
@@ -52,16 +52,16 @@ function findMonorepoRoot(): string | null {
|
|
|
52
52
|
|
|
53
53
|
/** the fresh dev-stack engine build to serve when running inside the Contrast
|
|
54
54
|
* monorepo dev checkout, or null when the installed runtime should serve
|
|
55
|
-
* (published CLI, packaged electron, or an isolated
|
|
55
|
+
* (published CLI, packaged electron, or an isolated PEACH_HOME). */
|
|
56
56
|
export function resolveDevCheckoutRuntimeRoot(): string | null {
|
|
57
57
|
// an explicit home that has a STAGED/active runtime is the isolation the
|
|
58
58
|
// CI/local-publish path sets up to validate the installed-runtime code path —
|
|
59
59
|
// honor that staged runtime. an explicit home with NO active runtime is just
|
|
60
|
-
// an isolated dev daemon (own lockfile, doesn't clobber ~/.
|
|
61
|
-
// still wants the dev build; and the default home (
|
|
60
|
+
// an isolated dev daemon (own lockfile, doesn't clobber ~/.peach), which
|
|
61
|
+
// still wants the dev build; and the default home (PEACH_HOME unset) always
|
|
62
62
|
// does. keying on "explicit home + a runtime deliberately staged there" keeps
|
|
63
63
|
// it structural, not a bespoke toggle.
|
|
64
|
-
if (process.env.
|
|
64
|
+
if (process.env.PEACH_HOME && readActiveRuntime()) return null
|
|
65
65
|
const root = findMonorepoRoot()
|
|
66
66
|
if (!root) return null
|
|
67
67
|
const devBuild = path.join(root, 'public/sootsim')
|
|
@@ -130,11 +130,11 @@ const RUNTIME_VERSION_HOSTNAME_SUFFIX = '.runtime.localhost'
|
|
|
130
130
|
export function runtimeVersionHostname(version: string): string {
|
|
131
131
|
const trimmed = version.trim()
|
|
132
132
|
if (!isValidRuntimeVersion(trimmed)) {
|
|
133
|
-
throw new Error(`invalid
|
|
133
|
+
throw new Error(`invalid peach runtime version: ${version}`)
|
|
134
134
|
}
|
|
135
135
|
const encoded = Buffer.from(trimmed, 'utf8').toString('hex')
|
|
136
136
|
const labels = encoded.match(/.{1,60}/g)
|
|
137
|
-
if (!labels) throw new Error(`invalid
|
|
137
|
+
if (!labels) throw new Error(`invalid peach runtime version: ${version}`)
|
|
138
138
|
return `${labels.join('.')}${RUNTIME_VERSION_HOSTNAME_SUFFIX}`
|
|
139
139
|
}
|
|
140
140
|
|
package/src/runtime-delivery.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
//
|
|
1
|
+
// peach's binding of the shared runtime-delivery machinery.
|
|
2
2
|
//
|
|
3
3
|
// the machinery itself (hosted manifest, sha256-verified tarballs, channels,
|
|
4
4
|
// channel resolution, and auto-update) lives in @contrast/runtime-delivery and
|
|
5
|
-
// knows nothing about
|
|
5
|
+
// knows nothing about peach. this file supplies peach's identity, public env
|
|
6
6
|
// overrides, and the contrast.dev/runtimes hosting layout.
|
|
7
7
|
//
|
|
8
8
|
// @contrast/runtime-delivery is an internal workspace package that is never
|
|
@@ -25,12 +25,12 @@ import { rnxPublicBrand } from './public-brand.ts'
|
|
|
25
25
|
export const DEFAULT_RUNTIME_CDN_ORIGIN = 'https://contrast.dev'
|
|
26
26
|
|
|
27
27
|
/** the official curated changelog and the machine-readable release feed. the
|
|
28
|
-
*
|
|
28
|
+
* peach site is static, so its /api traffic is owned by contrast.dev. */
|
|
29
29
|
export const RNX_CHANGELOG_URL = `${rnxPublicBrand.origin}/changelog`
|
|
30
30
|
export const RNX_CHANGELOG_API_URL = 'https://contrast.dev/api/changelog/sootsim'
|
|
31
31
|
|
|
32
32
|
export const RNX_RUNTIME_PRODUCT: RuntimeProduct = {
|
|
33
|
-
id: '
|
|
33
|
+
id: 'peach',
|
|
34
34
|
defaultCdnOrigin: DEFAULT_RUNTIME_CDN_ORIGIN,
|
|
35
35
|
manifestPath: '/runtimes/manifest.json',
|
|
36
36
|
tarballPath: (version) => `/runtimes/sootsim-runtime-${version}.tar.gz`,
|
|
@@ -39,8 +39,8 @@ export const RNX_RUNTIME_PRODUCT: RuntimeProduct = {
|
|
|
39
39
|
// vite/metro plugins serve, so its absence means the tarball is not one.
|
|
40
40
|
installedMarker: 'index.html',
|
|
41
41
|
env: {
|
|
42
|
-
cdnOrigin: '
|
|
43
|
-
channel: '
|
|
42
|
+
cdnOrigin: 'PEACH_CDN_ORIGIN',
|
|
43
|
+
channel: 'PEACH_RUNTIME_CHANNEL',
|
|
44
44
|
},
|
|
45
45
|
ensureHome: ensureRnxHome,
|
|
46
46
|
configFile: configFilePath,
|
|
@@ -20,7 +20,7 @@ export interface RunScreenshotsOverrides {
|
|
|
20
20
|
captureOnly?: boolean
|
|
21
21
|
composeOnly?: boolean
|
|
22
22
|
// copy/colors pulled from the team's org deck to overlay onto the plan's
|
|
23
|
-
// compose slides (
|
|
23
|
+
// compose slides (peach screenshot appstore --org … --repo …).
|
|
24
24
|
orgDeckFrames?: OrgDeckFrame[] | null
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// fetch the team's screenshot deck (the copy / colors founders set up in the
|
|
2
2
|
// org dashboard) and overlay it onto a screenshots plan, so the programmatic
|
|
3
|
-
// `
|
|
3
|
+
// `peach screenshot appstore --plan … --org … --repo …` flow renders the org's
|
|
4
4
|
// words + brand gradient instead of the local yaml's. the plan still owns
|
|
5
5
|
// which screen each slide captures and the device frame; the deck owns copy +
|
|
6
6
|
// colors. 3d scenes don't translate to the cli's 2d composer, so only copy and
|
|
@@ -246,7 +246,7 @@ export function loadScreenshotsPlan(planPath: string): NormalizedScreenshotsPlan
|
|
|
246
246
|
const deviceModel = readDeviceModel(root.device, null)
|
|
247
247
|
const captureOutDir = resolvePlanPath(
|
|
248
248
|
planDir,
|
|
249
|
-
readString(capture.out, path.join('.
|
|
249
|
+
readString(capture.out, path.join('.peach', 'screenshots', 'capture')),
|
|
250
250
|
)
|
|
251
251
|
const captureFrom = readOptionalString(capture.from)
|
|
252
252
|
const flowPath = readOptionalString(capture.flow)
|
|
@@ -335,7 +335,7 @@ export function loadScreenshotsPlan(planPath: string): NormalizedScreenshotsPlan
|
|
|
335
335
|
compose: {
|
|
336
336
|
outDir: resolvePlanPath(
|
|
337
337
|
planDir,
|
|
338
|
-
readString(compose.out, path.join('.
|
|
338
|
+
readString(compose.out, path.join('.peach', 'screenshots', 'exports')),
|
|
339
339
|
),
|
|
340
340
|
locale: readString(compose.locale, 'en'),
|
|
341
341
|
canvases: normalizeCanvasList(compose.canvases),
|
package/src/sim-client.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// SimClient — the typed, promise-based client every
|
|
1
|
+
// SimClient — the typed, promise-based client every peach frontend drives a
|
|
2
2
|
// sim through. it wraps a bridge transport (the CLI's ws bridge, or any
|
|
3
3
|
// InspectBridge-shaped channel) and reuses the existing inspect verbs as its
|
|
4
4
|
// implementation; it never re-implements tap resolution, find, settling, or
|
|
@@ -4,14 +4,14 @@ import type { RNXSkill } from '../types'
|
|
|
4
4
|
|
|
5
5
|
export const skill: RNXSkill = {
|
|
6
6
|
name: 'compat-check',
|
|
7
|
-
description: 'Check package compatibility with
|
|
7
|
+
description: 'Check package compatibility with peach',
|
|
8
8
|
type: 'review',
|
|
9
9
|
version: '1.0.0',
|
|
10
10
|
triggers: ['compatibility', 'compat', 'check package', 'supported packages'],
|
|
11
11
|
tools: [
|
|
12
12
|
{
|
|
13
13
|
name: 'check_compatibility',
|
|
14
|
-
description: 'Scan project dependencies for
|
|
14
|
+
description: 'Scan project dependencies for peach compatibility',
|
|
15
15
|
parameters: {
|
|
16
16
|
packageName: {
|
|
17
17
|
type: 'string',
|