peachsim 0.1.570 → 0.1.572
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 +108 -108
- 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 +28 -20
- 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 +3 -2
- package/cli/cloud-session.ts +12 -12
- package/cli/cloud-test-result-files.ts +97 -0
- 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 +173 -71
- 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 +176 -18
- 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 +4 -2
- package/cli/main.ts +14 -14
- package/cli/outbound-endpoints.ts +32 -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 +3 -2
- 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/jest-preset.cjs +2 -2
- 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 +116 -0
- package/dist-lib/cloud-test-args.mjs +86 -0
- 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/detox/jest-preset.cjs +2 -2
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +12 -12
- package/dist-lib/host/bridge-host.cjs +87 -77
- 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 +63 -73
- 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 +534 -520
- package/dist-lib/swift-compile.cjs +372 -0
- package/dist-lib/swift-compile.mjs +339 -0
- package/dist-lib/swift-package.cjs +78 -0
- package/dist-lib/swift-package.mjs +52 -0
- 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 +479 -161
- package/package.json +22 -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 +47 -47
- 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-test-args.ts +100 -0
- 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 +11 -10
- 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/swift-compile.ts +359 -0
- package/src/swift-package.ts +69 -0
- package/src/swift-submit.ts +3 -2
- package/src/vite-plugin-one.ts +8 -8
- package/src/vite-plugin-swift.ts +106 -110
- package/src/vite-plugin.ts +6 -19
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.572 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -125,11 +125,11 @@ var name, rnxPublicBrand;
|
|
|
125
125
|
var init_public_brand = __esm({
|
|
126
126
|
"src/public-brand.ts"() {
|
|
127
127
|
"use strict";
|
|
128
|
-
name = "
|
|
128
|
+
name = "Peach";
|
|
129
129
|
rnxPublicBrand = Object.freeze({
|
|
130
130
|
name,
|
|
131
131
|
packageName: "peachsim",
|
|
132
|
-
commandName: "
|
|
132
|
+
commandName: "peach",
|
|
133
133
|
domain: "rnxsim.com",
|
|
134
134
|
origin: "https://rnxsim.com"
|
|
135
135
|
});
|
|
@@ -138,9 +138,9 @@ var init_public_brand = __esm({
|
|
|
138
138
|
|
|
139
139
|
// src/home-paths.ts
|
|
140
140
|
function rnxHomeDir() {
|
|
141
|
-
const override = process.env[
|
|
141
|
+
const override = process.env[PEACH_HOME_ENV];
|
|
142
142
|
if (override && override.length > 0) return import_node_path4.default.resolve(override);
|
|
143
|
-
return import_node_path4.default.join((0, import_node_os.homedir)(), ".
|
|
143
|
+
return import_node_path4.default.join((0, import_node_os.homedir)(), ".peach");
|
|
144
144
|
}
|
|
145
145
|
function isSootsimDevCheckout() {
|
|
146
146
|
if (process.env.SOOTSIM_FORCE_DAEMON_INSTALL === "1") return false;
|
|
@@ -151,7 +151,7 @@ function isSootsimDevCheckout() {
|
|
|
151
151
|
if (!argv1) return false;
|
|
152
152
|
try {
|
|
153
153
|
const real = import_node_fs4.default.realpathSync(argv1);
|
|
154
|
-
return real.includes(`${import_node_path4.default.sep}packages${import_node_path4.default.sep}
|
|
154
|
+
return real.includes(`${import_node_path4.default.sep}packages${import_node_path4.default.sep}peachsim${import_node_path4.default.sep}`);
|
|
155
155
|
} catch {
|
|
156
156
|
return false;
|
|
157
157
|
}
|
|
@@ -306,10 +306,10 @@ function writeDaemonLockfile(data) {
|
|
|
306
306
|
const existing = readDaemonLockfile();
|
|
307
307
|
if (!existing) {
|
|
308
308
|
if (createDaemonLockfileExclusive(data)) return;
|
|
309
|
-
throw new Error("another
|
|
309
|
+
throw new Error("another peach daemon claimed the lockfile before this write");
|
|
310
310
|
}
|
|
311
311
|
if (!sameDaemonOwner(existing, data)) {
|
|
312
|
-
throw new Error("refusing to overwrite another
|
|
312
|
+
throw new Error("refusing to overwrite another peach daemon lockfile");
|
|
313
313
|
}
|
|
314
314
|
const tmp = `${lockfilePath}.${data.pid}.${(0, import_node_crypto.randomUUID)()}.tmp`;
|
|
315
315
|
import_node_fs4.default.writeFileSync(tmp, `${JSON.stringify(data, null, 2)}
|
|
@@ -317,7 +317,7 @@ function writeDaemonLockfile(data) {
|
|
|
317
317
|
try {
|
|
318
318
|
const current = readDaemonLockfile();
|
|
319
319
|
if (!current || !sameDaemonOwner(current, data)) {
|
|
320
|
-
throw new Error("
|
|
320
|
+
throw new Error("peach daemon lock ownership changed during heartbeat");
|
|
321
321
|
}
|
|
322
322
|
import_node_fs4.default.renameSync(tmp, lockfilePath);
|
|
323
323
|
} finally {
|
|
@@ -472,7 +472,7 @@ function removeDevBridgeLockfile(owner) {
|
|
|
472
472
|
} catch {
|
|
473
473
|
}
|
|
474
474
|
}
|
|
475
|
-
var import_node_crypto, import_node_fs4, import_node_os, import_node_path4,
|
|
475
|
+
var import_node_crypto, import_node_fs4, import_node_os, import_node_path4, PEACH_HOME_ENV, ACTIVE_RUNTIME_FILE, DAEMON_LOCKFILE, DEV_BRIDGES_DIR, CONFIG_FILE, DAEMON_HEARTBEAT_STALE_MS, DAEMON_LOCKFILE_MAX_BYTES, DAEMON_CLAIM_STALE_MS;
|
|
476
476
|
var init_home_paths = __esm({
|
|
477
477
|
"src/home-paths.ts"() {
|
|
478
478
|
"use strict";
|
|
@@ -480,7 +480,7 @@ var init_home_paths = __esm({
|
|
|
480
480
|
import_node_fs4 = __toESM(require("node:fs"), 1);
|
|
481
481
|
import_node_os = require("node:os");
|
|
482
482
|
import_node_path4 = __toESM(require("node:path"), 1);
|
|
483
|
-
|
|
483
|
+
PEACH_HOME_ENV = "PEACH_HOME";
|
|
484
484
|
ACTIVE_RUNTIME_FILE = "active";
|
|
485
485
|
DAEMON_LOCKFILE = "daemon.json";
|
|
486
486
|
DEV_BRIDGES_DIR = "dev-bridges";
|
|
@@ -597,7 +597,7 @@ var init_run_rnx = __esm({
|
|
|
597
597
|
RnxExit = class extends Error {
|
|
598
598
|
code;
|
|
599
599
|
constructor(code) {
|
|
600
|
-
super(`
|
|
600
|
+
super(`peach exited with code ${code}`);
|
|
601
601
|
this.name = "RnxExit";
|
|
602
602
|
this.code = code;
|
|
603
603
|
}
|
|
@@ -646,7 +646,7 @@ function isCliApiKeySecret(secret) {
|
|
|
646
646
|
return secret.startsWith("sk_rnx_");
|
|
647
647
|
}
|
|
648
648
|
function readApiKeyFromEnv() {
|
|
649
|
-
const envName = "
|
|
649
|
+
const envName = "PEACH_API_KEY";
|
|
650
650
|
const secret = process.env[envName]?.trim();
|
|
651
651
|
return secret && isCliApiKeySecret(secret) ? { secret, envName } : null;
|
|
652
652
|
}
|
|
@@ -700,11 +700,11 @@ function authHeaderOrExit(commandLabel) {
|
|
|
700
700
|
if (auth) return { auth, header: authHeaderValue(auth) };
|
|
701
701
|
process.stderr.write(
|
|
702
702
|
`
|
|
703
|
-
|
|
703
|
+
peach needs to be authenticated.
|
|
704
704
|
|
|
705
705
|
pick one:
|
|
706
|
-
\u2022 run \`
|
|
707
|
-
\u2022 set
|
|
706
|
+
\u2022 run \`peach login\` to sign in with your GH account
|
|
707
|
+
\u2022 set PEACH_API_KEY=sk_rnx_... (recommended for CI)
|
|
708
708
|
|
|
709
709
|
`
|
|
710
710
|
);
|
|
@@ -717,7 +717,7 @@ var init_auth = __esm({
|
|
|
717
717
|
init_shared_session();
|
|
718
718
|
init_run_rnx();
|
|
719
719
|
GITHUB_TOKEN_PREFIXES = ["ghs_", "ghp_", "gho_", "ghu_", "github_pat_"];
|
|
720
|
-
CHOOSE_ACCOUNT_HINT = "this sign-in belongs to several accounts; run `
|
|
720
|
+
CHOOSE_ACCOUNT_HINT = "this sign-in belongs to several accounts; run `peach login --account <name>` to choose the one to bill";
|
|
721
721
|
}
|
|
722
722
|
});
|
|
723
723
|
|
|
@@ -842,11 +842,19 @@ function resolveDevicePosture(model, posture) {
|
|
|
842
842
|
const supported = devices[model].supportedPostures;
|
|
843
843
|
return posture && supported?.includes(posture) ? posture : supported?.[0] ?? "closed";
|
|
844
844
|
}
|
|
845
|
-
function
|
|
845
|
+
function deviceDefaultOrientation(model, posture) {
|
|
846
|
+
if (model === "iphone-duo" && resolveDevicePosture(model, posture) === "open") {
|
|
847
|
+
return "landscape";
|
|
848
|
+
}
|
|
849
|
+
return "portrait";
|
|
850
|
+
}
|
|
851
|
+
function getDevice(model, posture, orientation) {
|
|
846
852
|
const device = devices[model];
|
|
847
853
|
if (!device.supportedPostures) return device;
|
|
848
854
|
const resolvedPosture = resolveDevicePosture(model, posture);
|
|
849
855
|
if (resolvedPosture === "closed") return device;
|
|
856
|
+
const resolvedOrientation = orientation ?? deviceDefaultOrientation(model, resolvedPosture);
|
|
857
|
+
const isRotatedPortrait = resolvedOrientation === "portrait";
|
|
850
858
|
return {
|
|
851
859
|
...device,
|
|
852
860
|
// inner display size from apple's ios 27 ui kit. corners and insets are
|
|
@@ -854,8 +862,8 @@ function getDevice(model, posture) {
|
|
|
854
862
|
// fits a 53pt circle within 0.4px, the silhouette sits 20.67pt outside the
|
|
855
863
|
// display on every edge as 16.33pt of black glass plus a 4.33pt rail, and
|
|
856
864
|
// the body itself curves at 75pt. the barrel is hidden when open.
|
|
857
|
-
width: 951,
|
|
858
|
-
height: 669,
|
|
865
|
+
width: isRotatedPortrait ? 669 : 951,
|
|
866
|
+
height: isRotatedPortrait ? 951 : 669,
|
|
859
867
|
statusBarHeight: 44,
|
|
860
868
|
cornerRadius: cornerRadii(53),
|
|
861
869
|
continuousCornerRadius: cornerRadii(53),
|
|
@@ -869,8 +877,9 @@ function getDevice(model, posture) {
|
|
|
869
877
|
// the closed outer display, so it takes the same 84pt inset: a ~50pt
|
|
870
878
|
// control at a ~23pt inset needs 73pt, and anything narrower would shift
|
|
871
879
|
// controls horizontally on unfold, defeating the continuous experience
|
|
872
|
-
// Apple states as the reason for the design.
|
|
873
|
-
|
|
880
|
+
// Apple states as the reason for the design. native bottom inset is 34;
|
|
881
|
+
// rotated portrait is top 82 / bottom 34 / right 0.
|
|
882
|
+
safeAreaInsets: isRotatedPortrait ? { top: 82, bottom: 34, left: 0, right: 0 } : { top: 0, bottom: 34, left: 0, right: 84 }
|
|
874
883
|
};
|
|
875
884
|
}
|
|
876
885
|
function listDeviceModels() {
|
|
@@ -1338,7 +1347,7 @@ var init_devices = __esm({
|
|
|
1338
1347
|
},
|
|
1339
1348
|
dynamicIsland: null,
|
|
1340
1349
|
// 84pt trailing Vertical Bar on the outer display (Apple iOS 27 UI kit).
|
|
1341
|
-
safeAreaInsets: { top: 0, bottom:
|
|
1350
|
+
safeAreaInsets: { top: 0, bottom: 34, left: 0, right: 84 },
|
|
1342
1351
|
iosVersion: "27.1",
|
|
1343
1352
|
keyboardHeight: 0,
|
|
1344
1353
|
physicalPPI: 460,
|
|
@@ -2092,7 +2101,7 @@ async function assertSelfContainedMetroArtifactAssets(bundle) {
|
|
|
2092
2101
|
descriptors = extractAssetDescriptors(bundle);
|
|
2093
2102
|
} catch (error) {
|
|
2094
2103
|
throw new Error(
|
|
2095
|
-
`
|
|
2104
|
+
`peach ios --remote bundle is not self-contained: ${error instanceof Error ? error.message : String(error)}`
|
|
2096
2105
|
);
|
|
2097
2106
|
}
|
|
2098
2107
|
let variants = 0;
|
|
@@ -2105,7 +2114,7 @@ async function assertSelfContainedMetroArtifactAssets(bundle) {
|
|
|
2105
2114
|
const hashes = descriptor.fileHashes;
|
|
2106
2115
|
if (!uris || !hashes || uris.length !== descriptor.scales.length || hashes.length !== descriptor.scales.length) {
|
|
2107
2116
|
throw new Error(
|
|
2108
|
-
`
|
|
2117
|
+
`peach ios --remote bundle is not self-contained: ${label} does not embed every scale variant`
|
|
2109
2118
|
);
|
|
2110
2119
|
}
|
|
2111
2120
|
const prefix = `data:${metroAssetContentType(descriptor.type)};base64,`;
|
|
@@ -2114,7 +2123,7 @@ async function assertSelfContainedMetroArtifactAssets(bundle) {
|
|
|
2114
2123
|
const expectedHash = hashes[index];
|
|
2115
2124
|
if (!uri.startsWith(prefix) || !/^[a-f0-9]{64}$/.test(expectedHash)) {
|
|
2116
2125
|
throw new Error(
|
|
2117
|
-
`
|
|
2126
|
+
`peach ios --remote bundle is not self-contained: ${label} scale ${descriptor.scales[index]} is not content-addressed embedded data`
|
|
2118
2127
|
);
|
|
2119
2128
|
}
|
|
2120
2129
|
let decoded;
|
|
@@ -2123,12 +2132,12 @@ async function assertSelfContainedMetroArtifactAssets(bundle) {
|
|
|
2123
2132
|
decoded = Uint8Array.from(binary, (character) => character.charCodeAt(0));
|
|
2124
2133
|
} catch {
|
|
2125
2134
|
throw new Error(
|
|
2126
|
-
`
|
|
2135
|
+
`peach ios --remote bundle is not self-contained: ${label} scale ${descriptor.scales[index]} has invalid embedded data`
|
|
2127
2136
|
);
|
|
2128
2137
|
}
|
|
2129
2138
|
if (await sha256HexBytes(decoded) !== expectedHash) {
|
|
2130
2139
|
throw new Error(
|
|
2131
|
-
`
|
|
2140
|
+
`peach ios --remote bundle is not self-contained: ${label} scale ${descriptor.scales[index]} bytes do not match their content hash`
|
|
2132
2141
|
);
|
|
2133
2142
|
}
|
|
2134
2143
|
variants++;
|
|
@@ -2251,13 +2260,13 @@ async function embedMetroAssetFiles(bundle, read) {
|
|
|
2251
2260
|
}
|
|
2252
2261
|
if (loaded.size === 0) {
|
|
2253
2262
|
throw new Error(
|
|
2254
|
-
`
|
|
2263
|
+
`peach ios --remote found no scale of ${site.descriptor.name}.${site.descriptor.type} in the asset dest graph for ${site.descriptor.httpServerLocation}`
|
|
2255
2264
|
);
|
|
2256
2265
|
}
|
|
2257
2266
|
const scales = [...loaded.keys()].sort((left, right) => left - right);
|
|
2258
2267
|
if (scales.length !== site.descriptor.scales.length && !site.scalesSpan) {
|
|
2259
2268
|
throw new Error(
|
|
2260
|
-
`
|
|
2269
|
+
`peach ios --remote could not narrow the scales of ${site.descriptor.name}.${site.descriptor.type} because its descriptor declares none`
|
|
2261
2270
|
);
|
|
2262
2271
|
}
|
|
2263
2272
|
let descriptorBytes = 0;
|
|
@@ -2289,7 +2298,7 @@ async function embedMetroAssetFiles(bundle, read) {
|
|
|
2289
2298
|
const code = parts.join("");
|
|
2290
2299
|
if (countNewlines(code) !== countNewlines(bundle)) {
|
|
2291
2300
|
throw new Error(
|
|
2292
|
-
"
|
|
2301
|
+
"peach Cloud asset embedding changed the bundle line count, which invalidates its source map"
|
|
2293
2302
|
);
|
|
2294
2303
|
}
|
|
2295
2304
|
return {
|
|
@@ -2444,11 +2453,11 @@ async function minify(code, sourceLine, options, withMap) {
|
|
|
2444
2453
|
...withMap ? { sourceMap: true } : {}
|
|
2445
2454
|
});
|
|
2446
2455
|
if (typeof result.code !== "string") {
|
|
2447
|
-
throw new Error(`
|
|
2456
|
+
throw new Error(`peach Cloud could not re-print the statement at line ${sourceLine}`);
|
|
2448
2457
|
}
|
|
2449
2458
|
const map = withMap && typeof result.map === "string" ? result.map : null;
|
|
2450
2459
|
if (withMap && map === null) {
|
|
2451
|
-
throw new Error(`
|
|
2460
|
+
throw new Error(`peach Cloud got no source map for the statement at line ${sourceLine}`);
|
|
2452
2461
|
}
|
|
2453
2462
|
return { code: result.code.trimEnd(), map, sourceLine };
|
|
2454
2463
|
}
|
|
@@ -2458,7 +2467,7 @@ async function minifyDefine(statement, moduleId, sourceLine, options, developmen
|
|
|
2458
2467
|
const define = layout.statements[0];
|
|
2459
2468
|
if (layout.statements.length !== 1 || define?.kind !== "define") {
|
|
2460
2469
|
throw new Error(
|
|
2461
|
-
`
|
|
2470
|
+
`peach Cloud could not re-read module ${moduleId} after minification: the minifier emitted ${layout.statements.length} statements rather than one \`__d(\` call.`
|
|
2462
2471
|
);
|
|
2463
2472
|
}
|
|
2464
2473
|
const factory = piece.code.slice(define.factory.start, define.factory.end);
|
|
@@ -2520,7 +2529,7 @@ async function buildRnxCloudArtifact(bundle, options = {}) {
|
|
|
2520
2529
|
const layout = (0, import_metro_production_bundle.readRNXMetroBundleLayout)(identity.source);
|
|
2521
2530
|
if (layout.moduleIdFailures > 0) {
|
|
2522
2531
|
throw new Error(
|
|
2523
|
-
`
|
|
2532
|
+
`peach Cloud could not read ${layout.moduleIdFailures} Metro module IDs from the bundle`
|
|
2524
2533
|
);
|
|
2525
2534
|
}
|
|
2526
2535
|
(0, import_metro_production_bundle.validateRNXMetroModulePaths)(identity.source, identity.modulePaths);
|
|
@@ -2610,8 +2619,8 @@ var init_metroCloudArtifact = __esm({
|
|
|
2610
2619
|
import_terser = require("terser");
|
|
2611
2620
|
init_metroAssetArtifact();
|
|
2612
2621
|
init_metroDebugSourceMap();
|
|
2613
|
-
MODULE_PATHS_REQUIRED = "
|
|
2614
|
-
SOURCE_MAP_REQUIRED = "
|
|
2622
|
+
MODULE_PATHS_REQUIRED = "peach Cloud requires a Metro bundle carrying rnx module identity. Build it through the published Metro plugin: withRNX(config).";
|
|
2623
|
+
SOURCE_MAP_REQUIRED = "peach Cloud development artifacts require the Metro source map for the bundle. Build it with --sourcemap-output, or serve the bundle with an inline source map.";
|
|
2615
2624
|
MINIFY_OPTIONS = {
|
|
2616
2625
|
ecma: 2020,
|
|
2617
2626
|
compress: false,
|
|
@@ -3761,7 +3770,7 @@ function responseError(status, text) {
|
|
|
3761
3770
|
);
|
|
3762
3771
|
}
|
|
3763
3772
|
function resolveCloudOrigin(value) {
|
|
3764
|
-
const configured = value?.trim() || process.env.
|
|
3773
|
+
const configured = value?.trim() || process.env.PEACH_CLOUD_ORIGIN?.trim();
|
|
3765
3774
|
const source = configured || DEFAULT_RNX_CLOUD_ORIGIN;
|
|
3766
3775
|
return normalizeCloudOrigin(source);
|
|
3767
3776
|
}
|
|
@@ -4295,7 +4304,7 @@ var init_cloud_client = __esm({
|
|
|
4295
4304
|
init_detect();
|
|
4296
4305
|
DEFAULT_RNX_CLOUD_ORIGIN = rnxPublicBrand.origin;
|
|
4297
4306
|
MAX_RNX_CLOUD_BUNDLE_BYTES = RNX_CLOUD_MAX_ARTIFACT_BYTES;
|
|
4298
|
-
REMOTE_COMMAND = "
|
|
4307
|
+
REMOTE_COMMAND = "peach remote";
|
|
4299
4308
|
MAX_ASSET_DEST_FILES = 25e3;
|
|
4300
4309
|
ACCOUNT_CHOICE_REFUSALS = /* @__PURE__ */ new Set([
|
|
4301
4310
|
"accountId is required",
|
|
@@ -5371,6 +5380,7 @@ async function probePort(port, buildIconProxyUrl, listeningProcess) {
|
|
|
5371
5380
|
function isSootSimSelfServer(server) {
|
|
5372
5381
|
const bundleId = server.bundleId?.trim().toLowerCase();
|
|
5373
5382
|
if (bundleId?.startsWith("dev.sootsim.")) return true;
|
|
5383
|
+
if (bundleId?.startsWith("dev.peachsim.")) return true;
|
|
5374
5384
|
return false;
|
|
5375
5385
|
}
|
|
5376
5386
|
var portCache = /* @__PURE__ */ new Map();
|
|
@@ -5506,8 +5516,8 @@ var import_meta = {};
|
|
|
5506
5516
|
var cached2 = null;
|
|
5507
5517
|
function getCliVersion() {
|
|
5508
5518
|
if (cached2 != null) return cached2;
|
|
5509
|
-
if (typeof
|
|
5510
|
-
cached2 =
|
|
5519
|
+
if (typeof __PEACH_CLI_VERSION__ !== "undefined" && typeof __PEACH_CLI_VERSION__ === "string" && __PEACH_CLI_VERSION__) {
|
|
5520
|
+
cached2 = __PEACH_CLI_VERSION__;
|
|
5511
5521
|
return cached2;
|
|
5512
5522
|
}
|
|
5513
5523
|
const candidates = [
|
|
@@ -5965,7 +5975,7 @@ function findMonorepoRoot() {
|
|
|
5965
5975
|
return null;
|
|
5966
5976
|
}
|
|
5967
5977
|
function resolveDevCheckoutRuntimeRoot() {
|
|
5968
|
-
if (process.env.
|
|
5978
|
+
if (process.env.PEACH_HOME && readActiveRuntime()) return null;
|
|
5969
5979
|
const root = findMonorepoRoot();
|
|
5970
5980
|
if (!root) return null;
|
|
5971
5981
|
const devBuild = import_path.default.join(root, "public/sootsim");
|
|
@@ -6019,7 +6029,7 @@ init_public_brand();
|
|
|
6019
6029
|
var DEFAULT_RUNTIME_CDN_ORIGIN = "https://contrast.dev";
|
|
6020
6030
|
var RNX_CHANGELOG_URL = `${rnxPublicBrand.origin}/changelog`;
|
|
6021
6031
|
var RNX_RUNTIME_PRODUCT = {
|
|
6022
|
-
id: "
|
|
6032
|
+
id: "peach",
|
|
6023
6033
|
defaultCdnOrigin: DEFAULT_RUNTIME_CDN_ORIGIN,
|
|
6024
6034
|
manifestPath: "/runtimes/manifest.json",
|
|
6025
6035
|
tarballPath: (version) => `/runtimes/sootsim-runtime-${version}.tar.gz`,
|
|
@@ -6028,8 +6038,8 @@ var RNX_RUNTIME_PRODUCT = {
|
|
|
6028
6038
|
// vite/metro plugins serve, so its absence means the tarball is not one.
|
|
6029
6039
|
installedMarker: "index.html",
|
|
6030
6040
|
env: {
|
|
6031
|
-
cdnOrigin: "
|
|
6032
|
-
channel: "
|
|
6041
|
+
cdnOrigin: "PEACH_CDN_ORIGIN",
|
|
6042
|
+
channel: "PEACH_RUNTIME_CHANNEL"
|
|
6033
6043
|
},
|
|
6034
6044
|
ensureHome: ensureRnxHome,
|
|
6035
6045
|
configFile: configFilePath,
|
|
@@ -6433,8 +6443,8 @@ function pidIsAlive(pid, sessionId) {
|
|
|
6433
6443
|
return true;
|
|
6434
6444
|
}
|
|
6435
6445
|
function resolveSootsimInvocation() {
|
|
6436
|
-
if (process.env.
|
|
6437
|
-
return { executable: process.env.
|
|
6446
|
+
if (process.env.PEACH_BIN) {
|
|
6447
|
+
return { executable: process.env.PEACH_BIN, prefixArgs: [] };
|
|
6438
6448
|
}
|
|
6439
6449
|
if (IS_STANDALONE) return rnxSelfInvocation();
|
|
6440
6450
|
if (process.versions.electron) {
|
|
@@ -6456,14 +6466,14 @@ function resolveSootsimInvocation() {
|
|
|
6456
6466
|
return { executable: process.argv[0], prefixArgs: [argv1] };
|
|
6457
6467
|
}
|
|
6458
6468
|
throw new Error(
|
|
6459
|
-
"
|
|
6469
|
+
"peach CLI not found. set PEACH_BIN to the path of the peach binary, or build the workspace CLI via `bun run --cwd packages/peachsim build:cli`."
|
|
6460
6470
|
);
|
|
6461
6471
|
}
|
|
6462
6472
|
function tryWorkspaceSootsim() {
|
|
6463
6473
|
try {
|
|
6464
6474
|
const sootsimDir = resolveSootsimPackageDir();
|
|
6465
6475
|
if (!sootsimDir) return null;
|
|
6466
|
-
const binaryName = `
|
|
6476
|
+
const binaryName = `peach-${process.platform === "win32" ? "windows" : process.platform}-${process.arch}${process.platform === "win32" ? ".exe" : ""}`;
|
|
6467
6477
|
const distBinary = import_node_path9.default.join(sootsimDir, "dist-bin", binaryName);
|
|
6468
6478
|
if (import_node_fs9.default.existsSync(distBinary)) return { executable: distBinary, prefixArgs: [] };
|
|
6469
6479
|
const distBin = import_node_path9.default.join(sootsimDir, "dist-cli", "bin.js");
|
|
@@ -6475,7 +6485,7 @@ function tryWorkspaceSootsim() {
|
|
|
6475
6485
|
const buildMtime = import_node_fs9.default.statSync(distBin).mtimeMs;
|
|
6476
6486
|
if (buildMtime < srcMtime) {
|
|
6477
6487
|
console.warn(
|
|
6478
|
-
`[
|
|
6488
|
+
`[peach] dist-cli/bin.js is older than agent-wrapper.ts \u2014 rebuild with \`bun run --cwd packages/peachsim build:cli\`.`
|
|
6479
6489
|
);
|
|
6480
6490
|
}
|
|
6481
6491
|
}
|
|
@@ -6627,7 +6637,7 @@ async function startSession(opts) {
|
|
|
6627
6637
|
if (existingLive) {
|
|
6628
6638
|
throw new AgentSessionError(
|
|
6629
6639
|
"ALREADY_RUNNING",
|
|
6630
|
-
`session already running for project=${project.id} provider=${provider} (session ${existingLive.id}, pid ${existingLive.wrapperPid}). end it first with \`
|
|
6640
|
+
`session already running for project=${project.id} provider=${provider} (session ${existingLive.id}, pid ${existingLive.wrapperPid}). end it first with \`peach agent end <sessionId>\`.`
|
|
6631
6641
|
);
|
|
6632
6642
|
}
|
|
6633
6643
|
const claudeSessionUuid = provider === "claude" ? (0, import_node_crypto4.randomUUID)() : void 0;
|
|
@@ -6918,7 +6928,7 @@ var AgentHost = class {
|
|
|
6918
6928
|
// every session.
|
|
6919
6929
|
sessionsBySocket = /* @__PURE__ */ new Map();
|
|
6920
6930
|
// every connected socket (regardless of role) — gets session-status
|
|
6921
|
-
// pushes so a CLI `
|
|
6931
|
+
// pushes so a CLI `peach agent sessions --watch` can react to state
|
|
6922
6932
|
// changes driven by another client.
|
|
6923
6933
|
allSockets = /* @__PURE__ */ new Set();
|
|
6924
6934
|
// agent wrappers also emit prompt-received from the FIFO reader, but the
|
|
@@ -8154,7 +8164,7 @@ var PlaneHost = class {
|
|
|
8154
8164
|
const root = this.realRoot(String(msg.root ?? ""));
|
|
8155
8165
|
if (!this.registered.has(root)) {
|
|
8156
8166
|
throw new PlaneNotRegisteredError(
|
|
8157
|
-
`no box has registered ${root}; start one with \`
|
|
8167
|
+
`no box has registered ${root}; start one with \`peach box\` there`
|
|
8158
8168
|
);
|
|
8159
8169
|
}
|
|
8160
8170
|
const existingId = this.byRoot.get(root);
|
|
@@ -8364,7 +8374,7 @@ function unsupportedSpecifier(specifier) {
|
|
|
8364
8374
|
);
|
|
8365
8375
|
}
|
|
8366
8376
|
function bridgeDeclaration(name2, specifier) {
|
|
8367
|
-
const notReady = (what) => JSON.stringify(`[
|
|
8377
|
+
const notReady = (what) => JSON.stringify(`[peach] replacement ${what} bridge is not ready`);
|
|
8368
8378
|
if (specifier === "react") {
|
|
8369
8379
|
return `const ${name2} = ${REACT_BRIDGE}; if (!${name2}) throw new Error(${notReady("React")});`;
|
|
8370
8380
|
}
|
|
@@ -8372,12 +8382,12 @@ function bridgeDeclaration(name2, specifier) {
|
|
|
8372
8382
|
return `const ${name2} = ${REACT_NATIVE_BRIDGE}; if (!${name2}) throw new Error(${notReady("React Native")});`;
|
|
8373
8383
|
}
|
|
8374
8384
|
if (isContrastKitSpecifier(specifier)) {
|
|
8375
|
-
return `const ${name2} = (globalThis.__contrast_kit_modules && globalThis.__contrast_kit_modules[${JSON.stringify(specifier)}]) || (${PACKAGE_BRIDGES} || {})[${JSON.stringify(specifier)}]; if (!${name2}) throw new Error(${JSON.stringify(`[
|
|
8385
|
+
return `const ${name2} = (globalThis.__contrast_kit_modules && globalThis.__contrast_kit_modules[${JSON.stringify(specifier)}]) || (${PACKAGE_BRIDGES} || {})[${JSON.stringify(specifier)}]; if (!${name2}) throw new Error(${JSON.stringify(`[peach] replacement package bridge ${specifier} is not ready`)});`;
|
|
8376
8386
|
}
|
|
8377
8387
|
if (JSX_RUNTIME_SPECIFIERS.has(specifier)) {
|
|
8378
8388
|
return `const ${name2} = (() => { const react = ${REACT_BRIDGE}; if (!react) throw new Error(${notReady("React")}); const jsx = (type, props, key) => react.createElement(type, key === undefined ? props : { ...props, key }); return { Fragment: react.Fragment, jsx, jsxs: jsx, jsxDEV: jsx }; })();`;
|
|
8379
8389
|
}
|
|
8380
|
-
return `const ${name2} = (${PACKAGE_BRIDGES} || {})[${JSON.stringify(specifier)}]; if (!${name2}) throw new Error(${JSON.stringify(`[
|
|
8390
|
+
return `const ${name2} = (${PACKAGE_BRIDGES} || {})[${JSON.stringify(specifier)}]; if (!${name2}) throw new Error(${JSON.stringify(`[peach] replacement package bridge ${specifier} is not ready`)});`;
|
|
8381
8391
|
}
|
|
8382
8392
|
var DEFAULT_INTEROP = "__rnxReplacementDefault";
|
|
8383
8393
|
var DEFAULT_INTEROP_DECLARATION = `const ${DEFAULT_INTEROP} = (bridge) => (bridge && bridge.__esModule ? bridge.default : bridge);`;
|
|
@@ -8538,7 +8548,7 @@ function sendJavaScript(req, res, source) {
|
|
|
8538
8548
|
function isReplacementModuleRequestUrl(rawUrl) {
|
|
8539
8549
|
if (!rawUrl) return false;
|
|
8540
8550
|
try {
|
|
8541
|
-
const pathname = new URL(rawUrl, "http://
|
|
8551
|
+
const pathname = new URL(rawUrl, "http://peach.local").pathname;
|
|
8542
8552
|
return pathname === REPLACEMENT_MODULE_ROUTE;
|
|
8543
8553
|
} catch {
|
|
8544
8554
|
return false;
|
|
@@ -8548,7 +8558,7 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
|
|
|
8548
8558
|
const rawUrl = req.url || "";
|
|
8549
8559
|
let url;
|
|
8550
8560
|
try {
|
|
8551
|
-
url = new URL(rawUrl, "http://
|
|
8561
|
+
url = new URL(rawUrl, "http://peach.local");
|
|
8552
8562
|
} catch {
|
|
8553
8563
|
return false;
|
|
8554
8564
|
}
|
|
@@ -9008,8 +9018,8 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
9008
9018
|
static USER_BOOT_LEASE_TTL_MS = 6e4;
|
|
9009
9019
|
static SIM_RECONNECT_TTL_MS = 3e4;
|
|
9010
9020
|
// abandoned-tab GC. the ws heartbeat only reaps sims whose socket went
|
|
9011
|
-
// dead — but a background tab from a prior `
|
|
9012
|
-
// keeps its socket alive (the page still pongs) forever, so `
|
|
9021
|
+
// dead — but a background tab from a prior `peach open` / QA / test run
|
|
9022
|
+
// keeps its socket alive (the page still pongs) forever, so `peach list`
|
|
9013
9023
|
// accretes dozens of zombie sims that all time out on every command (QA
|
|
9014
9024
|
// F21-3, carried F19-2). reap a sim only when it is provably nobody's:
|
|
9015
9025
|
// not primary, not user-focused, no CLI attached, no active lease, and no
|
|
@@ -9017,7 +9027,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
9017
9027
|
// terminal 4001 code, so the client closes the abandoned window instead
|
|
9018
9028
|
// of reconnecting the zombie straight back in.
|
|
9019
9029
|
static SIM_IDLE_REAP_TTL_MS = 30 * 6e4;
|
|
9020
|
-
// automation sims (spawned by the playwright driver: `
|
|
9030
|
+
// automation sims (spawned by the playwright driver: `peach open --driver
|
|
9021
9031
|
// playwright`, the factory/screenshot capture path — `meta.sootsimHostDriver
|
|
9022
9032
|
// === 'playwright'`) are unattended one-shot browsers, never a human's tab. a
|
|
9023
9033
|
// capture run opens one per slide/app/retry and the 30-min human/dev TTL lets
|
|
@@ -9047,7 +9057,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
9047
9057
|
// dropped, sim crashed) leave their server-side WebSocket sitting "open"
|
|
9048
9058
|
// forever. ping every WS_HEARTBEAT_INTERVAL_MS; if the previous round's
|
|
9049
9059
|
// ping was never answered, terminate(). that fires 'close' which runs the
|
|
9050
|
-
// sim-cleanup path and stops `
|
|
9060
|
+
// sim-cleanup path and stops `peach list` from showing 8 zombie
|
|
9051
9061
|
// sims that all time out on every command.
|
|
9052
9062
|
wsHeartbeatTimer = null;
|
|
9053
9063
|
wsIsAlive = /* @__PURE__ */ new WeakMap();
|
|
@@ -9396,7 +9406,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
9396
9406
|
expiresAt: Date.now() + _SootSimBridgeHost.USER_BOOT_LEASE_TTL_MS
|
|
9397
9407
|
};
|
|
9398
9408
|
process.stderr.write(
|
|
9399
|
-
`
|
|
9409
|
+
`peach booted ${booted.length} cli client(s)${hadLease ? " (overrode prior lease)" : ""}; held sim for user [${sim.id}]
|
|
9400
9410
|
`
|
|
9401
9411
|
);
|
|
9402
9412
|
this.recordSimAction(sim.id, "sim booted cli clients");
|
|
@@ -9511,7 +9521,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
9511
9521
|
ws.send(
|
|
9512
9522
|
JSON.stringify({
|
|
9513
9523
|
id: msg.id,
|
|
9514
|
-
error: `sim ${targetSim.id} is locked by another cli \u2014 use \`
|
|
9524
|
+
error: `sim ${targetSim.id} is locked by another cli \u2014 use \`peach claim ${targetSim.id} --force\` or \`peach open --new\``,
|
|
9515
9525
|
_locked: outcome.lock
|
|
9516
9526
|
})
|
|
9517
9527
|
);
|
|
@@ -9624,7 +9634,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
9624
9634
|
const claimed = claimDaemonLockfile(this.buildLockfileSnapshot());
|
|
9625
9635
|
if (!claimed) {
|
|
9626
9636
|
throw new Error(
|
|
9627
|
-
"another
|
|
9637
|
+
"another peach daemon wrote the lockfile during startup \u2014 aborting"
|
|
9628
9638
|
);
|
|
9629
9639
|
}
|
|
9630
9640
|
} catch (err) {
|
|
@@ -9742,7 +9752,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
9742
9752
|
return results;
|
|
9743
9753
|
}).catch((err) => {
|
|
9744
9754
|
const message = err instanceof Error ? err.message : String(err);
|
|
9745
|
-
console.error("[
|
|
9755
|
+
console.error("[peach] /__server-scan failed:", message);
|
|
9746
9756
|
return this.scanCache ?? [];
|
|
9747
9757
|
}).finally(() => {
|
|
9748
9758
|
this.inflightScan = null;
|
|
@@ -9750,7 +9760,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
9750
9760
|
return this.inflightScan;
|
|
9751
9761
|
}
|
|
9752
9762
|
// serves one staged camera fixture. addressed by basename inside
|
|
9753
|
-
// ~/.
|
|
9763
|
+
// ~/.peach/camera-fixtures, never by a caller-supplied path, so there is
|
|
9754
9764
|
// no traversal surface to defend: a name that is not a plain basename is
|
|
9755
9765
|
// rejected outright. range support is not optional here — chrome asks for
|
|
9756
9766
|
// byte ranges on media and cannot seek or loop a fixture without it.
|
|
@@ -9865,7 +9875,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
9865
9875
|
if (this.httpServer) this.writeLockfileSnapshot();
|
|
9866
9876
|
return;
|
|
9867
9877
|
}
|
|
9868
|
-
if (process.env.
|
|
9878
|
+
if (process.env.PEACH_HOME && isSootsimDevCheckout() && !readActiveRuntime()) {
|
|
9869
9879
|
return;
|
|
9870
9880
|
}
|
|
9871
9881
|
void this.runRuntimeUpdate("startup");
|
|
@@ -9880,7 +9890,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
9880
9890
|
this.runtimeUpdateInFlight = (async () => {
|
|
9881
9891
|
try {
|
|
9882
9892
|
if (reason === "startup") {
|
|
9883
|
-
process.stderr.write("
|
|
9893
|
+
process.stderr.write("peach: checking for runtime updates\u2026\n");
|
|
9884
9894
|
}
|
|
9885
9895
|
const result = await rnxRuntime.updateToLatest({
|
|
9886
9896
|
protectVersions: this.connectedRuntimeVersions()
|
|
@@ -9888,7 +9898,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
9888
9898
|
if (!result.updated || !result.latestVersion) {
|
|
9889
9899
|
if (reason === "startup") {
|
|
9890
9900
|
process.stderr.write(
|
|
9891
|
-
`
|
|
9901
|
+
`peach: runtime ${this.activeRuntimeVersion ?? "(none)"} is current
|
|
9892
9902
|
`
|
|
9893
9903
|
);
|
|
9894
9904
|
}
|
|
@@ -9896,7 +9906,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
9896
9906
|
}
|
|
9897
9907
|
const previousVersion = this.activeRuntimeVersion;
|
|
9898
9908
|
const active = this.setActiveRuntime(result.latestVersion);
|
|
9899
|
-
process.stderr.write(`
|
|
9909
|
+
process.stderr.write(`peach runtime updated to ${active.version} (${reason})
|
|
9900
9910
|
`);
|
|
9901
9911
|
try {
|
|
9902
9912
|
writeRuntimeUpgradeNotice({
|
|
@@ -9908,7 +9918,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
9908
9918
|
}
|
|
9909
9919
|
} catch (err) {
|
|
9910
9920
|
process.stderr.write(
|
|
9911
|
-
`
|
|
9921
|
+
`peach runtime update failed (${reason}): ${err instanceof Error ? err.message : String(err)}
|
|
9912
9922
|
`
|
|
9913
9923
|
);
|
|
9914
9924
|
} finally {
|
|
@@ -9921,7 +9931,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
9921
9931
|
} catch {
|
|
9922
9932
|
}
|
|
9923
9933
|
}
|
|
9924
|
-
process.stderr.write("
|
|
9934
|
+
process.stderr.write("peach: ready\n");
|
|
9925
9935
|
}
|
|
9926
9936
|
}
|
|
9927
9937
|
})();
|
|
@@ -10175,7 +10185,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
10175
10185
|
if (!baseDir) {
|
|
10176
10186
|
res.writeHead(503, { "Content-Type": "text/plain; charset=utf-8" });
|
|
10177
10187
|
res.end(
|
|
10178
|
-
versionedRuntimeRequest ? `
|
|
10188
|
+
versionedRuntimeRequest ? `peach: runtime ${requestedRuntime ?? "(invalid version origin)"} is not installed. run \`peach open\` from that app again.` : "peach: no active runtime installed. run `peach runtime install` to fetch one."
|
|
10179
10189
|
);
|
|
10180
10190
|
return;
|
|
10181
10191
|
}
|
|
@@ -10328,7 +10338,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
10328
10338
|
this.sweepRestorableSims(now);
|
|
10329
10339
|
this.reapIdleSims(now);
|
|
10330
10340
|
}
|
|
10331
|
-
// GC abandoned sims so `
|
|
10341
|
+
// GC abandoned sims so `peach list` stays usable across long dev / QA /
|
|
10332
10342
|
// test sessions (F21-3). conservative on purpose: a sim is only reaped
|
|
10333
10343
|
// when every "someone cares about this" signal is absent.
|
|
10334
10344
|
//
|
|
@@ -10344,7 +10354,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
10344
10354
|
// using is the primary and/or holds a fresh user-active lease; one that is
|
|
10345
10355
|
// none of those and idle past the TTL is abandoned regardless of a stale
|
|
10346
10356
|
// focus flag.
|
|
10347
|
-
// automation sims are spawned by the playwright driver (`
|
|
10357
|
+
// automation sims are spawned by the playwright driver (`peach open
|
|
10348
10358
|
// --driver playwright`, the factory/screenshot capture path), which tags them
|
|
10349
10359
|
// with `meta.sootsimHostDriver === 'playwright'` via the host's addInitScript.
|
|
10350
10360
|
// they are unattended one-shot browsers, never a human's tab, so they get a
|
|
@@ -10747,7 +10757,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
10747
10757
|
const candidates = this.getDefaultSimCandidates();
|
|
10748
10758
|
if (candidates.length > 1) {
|
|
10749
10759
|
throw new Error(
|
|
10750
|
-
`multiple sims are connected: ${candidates.map((sim) => sim.id).join(", ")}; run \`
|
|
10760
|
+
`multiple sims are connected: ${candidates.map((sim) => sim.id).join(", ")}; run \`peach use <sim>\` or pass \`--sim <sim>\``
|
|
10751
10761
|
);
|
|
10752
10762
|
}
|
|
10753
10763
|
const candidate = candidates[0];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.572 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.572 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.572 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
|
|
3
3
|
// src/host/fetch-proxy-overrides.ts
|
|
4
4
|
var FETCH_PROXY_BROWSER_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36";
|