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/cli/shell-init.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
PEACH_CLOUD_SESSION_ENV,
|
|
3
3
|
RNX_SHELL_UPDATE_SET_PREFIX,
|
|
4
4
|
RNX_SHELL_UPDATE_UNSET,
|
|
5
5
|
} from './cloud-session'
|
|
6
6
|
|
|
7
7
|
export function renderRnxShellInit(shell: string): string {
|
|
8
8
|
if (shell !== 'bash' && shell !== 'zsh') {
|
|
9
|
-
throw new Error('
|
|
9
|
+
throw new Error('Peach shell integration supports bash and zsh')
|
|
10
10
|
}
|
|
11
|
-
return `
|
|
12
|
-
local -a
|
|
13
|
-
local
|
|
14
|
-
local
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
return `peach() {
|
|
12
|
+
local -a _peach_shell_args
|
|
13
|
+
local _peach_shell_command _peach_shell_create _peach_shell_update
|
|
14
|
+
local _peach_shell_session _peach_shell_status _peach_shell_traced
|
|
15
|
+
_peach_shell_args=("$@")
|
|
16
|
+
_peach_shell_command=''
|
|
17
|
+
_peach_shell_create=0
|
|
18
18
|
while [ "$#" -gt 0 ]; do
|
|
19
19
|
case "$1" in
|
|
20
20
|
-h|--help|-V|--version|-v|--verbose|--headless) shift ;;
|
|
@@ -23,76 +23,76 @@ export function renderRnxShellInit(shell: string): string {
|
|
|
23
23
|
;;
|
|
24
24
|
--) break ;;
|
|
25
25
|
-*) shift ;;
|
|
26
|
-
*)
|
|
26
|
+
*) _peach_shell_command="$1"; shift; break ;;
|
|
27
27
|
esac
|
|
28
28
|
done
|
|
29
|
-
case "$
|
|
29
|
+
case "$_peach_shell_command" in
|
|
30
30
|
claim|close) ;;
|
|
31
31
|
ios)
|
|
32
|
-
for
|
|
33
|
-
if [ "$
|
|
34
|
-
|
|
32
|
+
for _peach_shell_session in "$@"; do
|
|
33
|
+
if [ "$_peach_shell_session" = '--remote' ]; then
|
|
34
|
+
_peach_shell_create=1
|
|
35
35
|
break
|
|
36
36
|
fi
|
|
37
37
|
done
|
|
38
|
-
if [ "$
|
|
39
|
-
command
|
|
38
|
+
if [ "$_peach_shell_create" -ne 1 ]; then
|
|
39
|
+
command peach "\${_peach_shell_args[@]}"
|
|
40
40
|
return $?
|
|
41
41
|
fi
|
|
42
42
|
;;
|
|
43
43
|
*)
|
|
44
|
-
command
|
|
44
|
+
command peach "\${_peach_shell_args[@]}"
|
|
45
45
|
return $?
|
|
46
46
|
;;
|
|
47
47
|
esac
|
|
48
48
|
|
|
49
49
|
if { [ -n "\${BASH_VERSION:-}" ] && [ "\${BASH_SUBSHELL:-0}" -ne 0 ]; } ||
|
|
50
50
|
{ [ -n "\${ZSH_VERSION:-}" ] && [ "\${ZSH_SUBSHELL:-0}" -ne 0 ]; }; then
|
|
51
|
-
printf '%s\\n' '
|
|
51
|
+
printf '%s\\n' 'peach remote simulator lifecycle commands must run directly in the current shell, not in a pipeline or command substitution' >&2
|
|
52
52
|
return 1
|
|
53
53
|
fi
|
|
54
54
|
if ( : >&9 ) 2>/dev/null; then
|
|
55
|
-
printf '%s\\n' '
|
|
55
|
+
printf '%s\\n' 'peach remote simulator shell integration requires file descriptor 9 to be unused' >&2
|
|
56
56
|
return 1
|
|
57
57
|
fi
|
|
58
|
-
if ! ( export ${
|
|
59
|
-
printf '%s\\n' '
|
|
58
|
+
if ! ( export ${PEACH_CLOUD_SESSION_ENV}=__peach_shell_probe && unset ${PEACH_CLOUD_SESSION_ENV} ) 2>/dev/null; then
|
|
59
|
+
printf '%s\\n' 'peach remote simulator shell integration cannot update PEACH_CLOUD_SESSION in this shell' >&2
|
|
60
60
|
return 1
|
|
61
61
|
fi
|
|
62
62
|
|
|
63
63
|
case "$-" in
|
|
64
|
-
*x*)
|
|
65
|
-
*)
|
|
64
|
+
*x*) _peach_shell_traced=1; set +x ;;
|
|
65
|
+
*) _peach_shell_traced=0 ;;
|
|
66
66
|
esac
|
|
67
67
|
exec 9>&1
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
_peach_shell_update="$(PEACH_SHELL_UPDATE_FD=3 command peach "\${_peach_shell_args[@]}" 3>&1 1>&9)"
|
|
69
|
+
_peach_shell_status=$?
|
|
70
70
|
exec 9>&-
|
|
71
71
|
|
|
72
|
-
if [ "$
|
|
73
|
-
case "$
|
|
72
|
+
if [ "$_peach_shell_status" -eq 0 ]; then
|
|
73
|
+
case "$_peach_shell_update" in
|
|
74
74
|
${RNX_SHELL_UPDATE_SET_PREFIX}*)
|
|
75
|
-
|
|
76
|
-
case "$
|
|
77
|
-
''|*$'\\n'*)
|
|
78
|
-
*) export ${
|
|
75
|
+
_peach_shell_session="\${_peach_shell_update#${RNX_SHELL_UPDATE_SET_PREFIX}}"
|
|
76
|
+
case "$_peach_shell_session" in
|
|
77
|
+
''|*$'\\n'*) _peach_shell_status=1 ;;
|
|
78
|
+
*) export ${PEACH_CLOUD_SESSION_ENV}="$_peach_shell_session" || _peach_shell_status=$? ;;
|
|
79
79
|
esac
|
|
80
80
|
;;
|
|
81
81
|
${RNX_SHELL_UPDATE_UNSET})
|
|
82
|
-
unset ${
|
|
82
|
+
unset ${PEACH_CLOUD_SESSION_ENV} || _peach_shell_status=$?
|
|
83
83
|
;;
|
|
84
|
-
*)
|
|
84
|
+
*) _peach_shell_status=1 ;;
|
|
85
85
|
esac
|
|
86
|
-
if [ "$
|
|
87
|
-
printf '%s\\n' '
|
|
88
|
-
elif [ "$
|
|
89
|
-
command
|
|
90
|
-
|
|
86
|
+
if [ "$_peach_shell_status" -ne 0 ]; then
|
|
87
|
+
printf '%s\\n' 'peach refused an invalid shell session update' >&2
|
|
88
|
+
elif [ "$_peach_shell_create" -eq 1 ]; then
|
|
89
|
+
command peach __cloud-confirm
|
|
90
|
+
_peach_shell_status=$?
|
|
91
91
|
fi
|
|
92
92
|
fi
|
|
93
93
|
|
|
94
|
-
if [ "$
|
|
95
|
-
return "$
|
|
94
|
+
if [ "$_peach_shell_traced" -eq 1 ]; then set -x; fi
|
|
95
|
+
return "$_peach_shell_status"
|
|
96
96
|
}
|
|
97
97
|
`
|
|
98
98
|
}
|
package/cli/ui.ts
CHANGED
|
@@ -32,7 +32,7 @@ export function failure(value: string): string {
|
|
|
32
32
|
|
|
33
33
|
export function printBrand(subtitle?: string): void {
|
|
34
34
|
console.log()
|
|
35
|
-
console.log(` ${accent('◤◢')} ${bold('
|
|
35
|
+
console.log(` ${accent('◤◢')} ${bold('peach')}`)
|
|
36
36
|
if (subtitle) console.log(` ${muted(subtitle)}`)
|
|
37
37
|
}
|
|
38
38
|
|
package/cli/ws-bridge.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
//
|
|
1
|
+
// peach CLI ↔ sim WS bridge
|
|
2
2
|
//
|
|
3
|
-
// the
|
|
3
|
+
// the peach runtime opens a WebSocket server (default port 7668) that
|
|
4
4
|
// accepts JSON commands like `{ type: 'evaluate', code: 'window.__sootsimTest.getNodeCount()' }`
|
|
5
5
|
// or `{ type: 'call', path: 'SootSim.bridges.mainShell.launchApp', args: ['photos'] }`
|
|
6
6
|
// and responds with `{ id, result }` or `{ id, error }`. CLI commands use
|
|
7
|
-
// this to drive a running
|
|
7
|
+
// this to drive a running peach instance from the terminal.
|
|
8
8
|
|
|
9
9
|
import fs from 'node:fs'
|
|
10
10
|
import path from 'node:path'
|
|
@@ -35,8 +35,8 @@ import type { WsBridgeCommand } from '../src/bridge-contract'
|
|
|
35
35
|
// --- bridge world resolution ---------------------------------------------
|
|
36
36
|
//
|
|
37
37
|
// two bridge kinds can coexist on one machine: Vite dev-shell bridges
|
|
38
|
-
// (~/.
|
|
39
|
-
// daemon runtime (~/.
|
|
38
|
+
// (~/.peach/dev-bridges/<port>.json, shells served by Vite) and the installed
|
|
39
|
+
// daemon runtime (~/.peach/daemon.json, shell served by the daemon's own
|
|
40
40
|
// http server). every default — the ws port a command connects to AND the
|
|
41
41
|
// shell base URL `open` builds its page from — must come from the SAME
|
|
42
42
|
// world, or `open` polls one bridge while the sim registers on the other
|
|
@@ -51,7 +51,7 @@ export interface BridgeWorld {
|
|
|
51
51
|
shellBaseUrl: string
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
// where this invocation is running. the same
|
|
54
|
+
// where this invocation is running. the same peach commands work in four
|
|
55
55
|
// places, and the placement is what a command consults instead of growing a
|
|
56
56
|
// second spelling per place. host and local-box share one transport today —
|
|
57
57
|
// a local box mounts this machine's checkout and drives this machine's
|
|
@@ -59,12 +59,12 @@ export interface BridgeWorld {
|
|
|
59
59
|
// cloud box is the one that moves the endpoint, and it does not exist yet.
|
|
60
60
|
export type RnxPlacement = 'host' | 'local-box' | 'cloud-box'
|
|
61
61
|
|
|
62
|
-
// set by `
|
|
62
|
+
// set by `peach box` on the shell's child processes. the box is the only thing
|
|
63
63
|
// that may set it; nothing infers a placement from cwd or heuristics.
|
|
64
|
-
export const
|
|
64
|
+
export const PEACH_PLACEMENT_ENV = 'PEACH_PLACEMENT'
|
|
65
65
|
|
|
66
66
|
export function resolvePlacement(): RnxPlacement {
|
|
67
|
-
return process.env[
|
|
67
|
+
return process.env[PEACH_PLACEMENT_ENV] === 'local-box' ? 'local-box' : 'host'
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
/** the ws endpoint a command connects to. the single place a bridge URL is
|
|
@@ -267,7 +267,7 @@ export function resolveBridgePortForPin(pin: {
|
|
|
267
267
|
if (pin.explicitPort) return { port: pin.wsPort }
|
|
268
268
|
return {
|
|
269
269
|
error:
|
|
270
|
-
`no live
|
|
270
|
+
`no live peach world serves ${pin.baseUrl} — start that shell first, ` +
|
|
271
271
|
'or name its bridge with --port <port>',
|
|
272
272
|
}
|
|
273
273
|
}
|
|
@@ -282,7 +282,7 @@ export function resolveBridgePortForPin(pin: {
|
|
|
282
282
|
/** default ws bridge port for CLI commands: the fresh dev bridge when a vite
|
|
283
283
|
* shell is live, else the fresh daemon, else the hardcoded default. one
|
|
284
284
|
* deterministic answer regardless of how the CLI was invoked (global binary
|
|
285
|
-
* vs repo checkout) — invocation-path heuristics made `
|
|
285
|
+
* vs repo checkout) — invocation-path heuristics made `peach list` flap
|
|
286
286
|
* between worlds. */
|
|
287
287
|
export function resolveDefaultBridgePort(): number {
|
|
288
288
|
return resolveBridgeWorld().bridgePort
|
|
@@ -372,7 +372,7 @@ function describeSimIdSource(
|
|
|
372
372
|
source: ParsedBridgeCliArgs['simIdSource'] | undefined,
|
|
373
373
|
): string {
|
|
374
374
|
if (source === 'flag') return 'via --sim'
|
|
375
|
-
if (source === 'saved') return 'saved via `
|
|
375
|
+
if (source === 'saved') return 'saved via `peach use`'
|
|
376
376
|
return 'primary fallback — no sim pinned'
|
|
377
377
|
}
|
|
378
378
|
|
|
@@ -399,7 +399,7 @@ export interface BridgeSimInfo {
|
|
|
399
399
|
documentFocused?: boolean
|
|
400
400
|
/** registration kind — 'sootsim' (default) or 'contrast'. used by the
|
|
401
401
|
* `contrast` CLI to filter, and by tooling that wants to distinguish a
|
|
402
|
-
* Contrast IDE tab from a regular
|
|
402
|
+
* Contrast IDE tab from a regular peach runtime. */
|
|
403
403
|
kind?: string
|
|
404
404
|
/** opaque metadata supplied at register time (projectId, route, the
|
|
405
405
|
* attached iOS sim id, etc). free-form by design. */
|
|
@@ -477,7 +477,7 @@ const BRIDGE_VALUE_FLAGS_TABLE: readonly {
|
|
|
477
477
|
},
|
|
478
478
|
{
|
|
479
479
|
// `--sim` is the canonical target flag; `--session` / `--tab` are
|
|
480
|
-
// documented aliases (CLAUDE.md, the
|
|
480
|
+
// documented aliases (CLAUDE.md, the peach agent skills, and engine docs all
|
|
481
481
|
// say `--session <id>`). without these aliases an agent following the docs
|
|
482
482
|
// would have `--session ef` silently ignored and get the *currently
|
|
483
483
|
// pinned* sim's tree instead — wrong-app data with no error.
|
|
@@ -684,7 +684,7 @@ export function createBridge(wsPort: number, opts: WsBridgeOptions = {}): WsBrid
|
|
|
684
684
|
`\n ⚠ ${msg._otherCliCount} other CLI identity/identities are driving this sim\n` +
|
|
685
685
|
' taps, scrolls, and keyboard input from multiple agents will collide on\n' +
|
|
686
686
|
' the same screen state (this is not a bridge throughput limit).\n' +
|
|
687
|
-
' use `
|
|
687
|
+
' use `peach open --new` for an isolated sim per agent.\n\n',
|
|
688
688
|
)
|
|
689
689
|
}
|
|
690
690
|
|
|
@@ -753,7 +753,7 @@ export function createBridge(wsPort: number, opts: WsBridgeOptions = {}): WsBrid
|
|
|
753
753
|
|
|
754
754
|
// re-resolve the saved pin per send for bridges that were not
|
|
755
755
|
// explicitly `--sim`-targeted. a poll loop (`wait ready`) started
|
|
756
|
-
// before a concurrent `
|
|
756
|
+
// before a concurrent `peach open` finished connecting would
|
|
757
757
|
// otherwise stay on the primary fallback for its whole budget, probing
|
|
758
758
|
// an unrelated (often empty) sim while the intended one connects and
|
|
759
759
|
// pins itself mid-wait. falling back to the startup pin keeps the
|
|
@@ -828,8 +828,8 @@ export function createBridge(wsPort: number, opts: WsBridgeOptions = {}): WsBrid
|
|
|
828
828
|
// agents end up recording the wrong app.
|
|
829
829
|
throw new Error(
|
|
830
830
|
`saved sim ${sentSimId} is gone${message.slice(missingSimMessage.length)}; ` +
|
|
831
|
-
'run `
|
|
832
|
-
`\`
|
|
831
|
+
'run `peach list` and ' +
|
|
832
|
+
`\`peach use <sim>\`, or open a fresh sim`,
|
|
833
833
|
)
|
|
834
834
|
}
|
|
835
835
|
throw error
|
|
@@ -870,10 +870,10 @@ export function createBridge(wsPort: number, opts: WsBridgeOptions = {}): WsBrid
|
|
|
870
870
|
}
|
|
871
871
|
} catch {}
|
|
872
872
|
ws.close()
|
|
873
|
-
// clear the grace timer on a real close, or a one-shot `
|
|
873
|
+
// clear the grace timer on a real close, or a one-shot `peach` command is
|
|
874
874
|
// held on the event loop for the full 250ms after its work is done. that
|
|
875
875
|
// delay lands directly in in-box prompt latency, since the shell spawns
|
|
876
|
-
//
|
|
876
|
+
// peach and waits on child close.
|
|
877
877
|
const terminateGrace = setTimeout(() => {
|
|
878
878
|
if (ws.readyState !== WebSocket.CLOSED) {
|
|
879
879
|
ws.terminate()
|
|
@@ -969,7 +969,7 @@ export async function checkSimHealth(
|
|
|
969
969
|
' and launch/transition animations will not complete.\n' +
|
|
970
970
|
(candidate
|
|
971
971
|
? ` another open sim looks usable: ${candidate}; target it with --sim.\n`
|
|
972
|
-
: ' run `
|
|
972
|
+
: ' run `peach list` to find the visible sim and target it with --sim.\n') +
|
|
973
973
|
' page-level window.focus() cannot unhide a browser tab.\n\n',
|
|
974
974
|
)
|
|
975
975
|
return { hidden: true, warned: true, simId: health.simId }
|
|
@@ -981,7 +981,7 @@ export async function checkSimHealth(
|
|
|
981
981
|
}
|
|
982
982
|
|
|
983
983
|
/**
|
|
984
|
-
* Convenience: run arbitrary JavaScript in the
|
|
984
|
+
* Convenience: run arbitrary JavaScript in the peach page and return the
|
|
985
985
|
* result. Hides the `type: 'evaluate'` message shape. Read-only by default —
|
|
986
986
|
* pass `{ acquireLock: true }` when the eval mutates user-facing state so
|
|
987
987
|
* the server takes/refreshes the cli lease and blocks concurrent agents.
|
package/detox/config-loader.ts
CHANGED
|
@@ -128,7 +128,7 @@ export function toRNXConfig(
|
|
|
128
128
|
return {
|
|
129
129
|
testFiles: findDetoxTestFiles(projectDir, config),
|
|
130
130
|
testTimeout: config?.testRunner?.jest?.setupTimeout || 120000,
|
|
131
|
-
sootsimUrl: process.env.
|
|
131
|
+
sootsimUrl: process.env.PEACH_URL || 'http://localhost:5173',
|
|
132
132
|
deviceModel: mapDetoxDevice(config),
|
|
133
133
|
maxWorkers: 1,
|
|
134
134
|
}
|
package/detox/index.ts
CHANGED
|
@@ -42,12 +42,12 @@ import type { Browser, BrowserContext, Page } from 'playwright'
|
|
|
42
42
|
export { by }
|
|
43
43
|
export type { SootSimElement } from './element-types'
|
|
44
44
|
|
|
45
|
-
const BASE_URL = process.env.
|
|
45
|
+
const BASE_URL = process.env.PEACH_URL || 'http://localhost:5173'
|
|
46
46
|
const SCREENSHOT_DIR =
|
|
47
|
-
process.env.
|
|
47
|
+
process.env.PEACH_SCREENSHOT_DIR ||
|
|
48
48
|
path.join(process.cwd(), 'test', 'detox-driver', 'screenshots')
|
|
49
49
|
const DETOX_PLATFORM =
|
|
50
|
-
process.env.
|
|
50
|
+
process.env.PEACH_PLATFORM === 'android' ? ('android' as const) : ('ios' as const)
|
|
51
51
|
|
|
52
52
|
// shared state -- playwright page and browser
|
|
53
53
|
let _browser: Browser | null = null
|
|
@@ -723,7 +723,7 @@ function decodePngDataUrl(dataUrl: string): Buffer {
|
|
|
723
723
|
const match = /^data:image\/png;base64,(.+)$/.exec(dataUrl)
|
|
724
724
|
if (!match) {
|
|
725
725
|
throw new Error(
|
|
726
|
-
`
|
|
726
|
+
`peach screenshot bridge returned a non-png payload: ${JSON.stringify(dataUrl.slice(0, 120))}`,
|
|
727
727
|
)
|
|
728
728
|
}
|
|
729
729
|
return Buffer.from(match[1], 'base64')
|
|
@@ -770,14 +770,14 @@ async function captureSootsimPngFast(opts?: {
|
|
|
770
770
|
const screenshot = (window as { SootSim?: { bridges?: { screenshot?: unknown } } })
|
|
771
771
|
.SootSim?.bridges?.screenshot as ((opts?: unknown) => Promise<string>) | undefined
|
|
772
772
|
if (typeof screenshot !== 'function') {
|
|
773
|
-
throw new Error('
|
|
773
|
+
throw new Error('peach screenshot bridge is not installed')
|
|
774
774
|
}
|
|
775
775
|
return screenshot(captureOpts)
|
|
776
776
|
},
|
|
777
777
|
{ crop: opts?.crop, format: 'png' },
|
|
778
778
|
)
|
|
779
779
|
if (!dataUrl) {
|
|
780
|
-
throw new Error('
|
|
780
|
+
throw new Error('peach screenshot bridge returned an empty image')
|
|
781
781
|
}
|
|
782
782
|
return decodePngDataUrl(dataUrl)
|
|
783
783
|
}
|
|
@@ -817,7 +817,7 @@ async function captureSootsimPng(opts?: {
|
|
|
817
817
|
previous = current
|
|
818
818
|
}
|
|
819
819
|
throw new Error(
|
|
820
|
-
`
|
|
820
|
+
`peach screenshot did not reach ${REQUIRED_IDENTICAL_PROOF_FRAMES} identical idle frames in ${attempts} captures`,
|
|
821
821
|
)
|
|
822
822
|
} finally {
|
|
823
823
|
await setSootsimCursorCaptureActive(page, false)
|
|
@@ -1695,7 +1695,7 @@ export const device = {
|
|
|
1695
1695
|
|
|
1696
1696
|
// record the SootSim canvas via the engine's headless recorder
|
|
1697
1697
|
// (window.__sootsimRecorder — @rnx/plugin-recording). this is the
|
|
1698
|
-
// SAME code path `
|
|
1698
|
+
// SAME code path `peach record video` drives, NOT the rail-button
|
|
1699
1699
|
// path (SootSim.bridges.startRecording wires the dialog state machine
|
|
1700
1700
|
// and never stashes the resulting blob into __sootsimRecorder.lastBlob,
|
|
1701
1701
|
// which is what getBlobBase64 streams from).
|
|
@@ -1738,7 +1738,7 @@ export const device = {
|
|
|
1738
1738
|
},
|
|
1739
1739
|
|
|
1740
1740
|
// stop the headless recorder, stream the resulting blob in chunks (same
|
|
1741
|
-
// protocol as `
|
|
1741
|
+
// protocol as `peach record`), and write the webm to outPath.
|
|
1742
1742
|
async stopAndSaveBridgeRecording(outPath: string): Promise<string> {
|
|
1743
1743
|
const page = getPage()
|
|
1744
1744
|
const stopResult = await page.evaluate(async () => {
|
|
@@ -1795,7 +1795,7 @@ export const device = {
|
|
|
1795
1795
|
},
|
|
1796
1796
|
{ offset, chunk: CHUNK },
|
|
1797
1797
|
)
|
|
1798
|
-
if (!result) throw new Error('
|
|
1798
|
+
if (!result) throw new Error('peach recorder produced no blob')
|
|
1799
1799
|
chunks.push(Buffer.from(result.data, 'base64'))
|
|
1800
1800
|
offset = result.offset
|
|
1801
1801
|
if (result.done) break
|
|
@@ -1863,7 +1863,7 @@ export const device = {
|
|
|
1863
1863
|
const token = `motion-${process.pid}-${Date.now()}-${Math.random()}`
|
|
1864
1864
|
const settleMs = options.settleMs ?? 0
|
|
1865
1865
|
if (!Number.isFinite(settleMs) || settleMs < 0) {
|
|
1866
|
-
throw new Error('
|
|
1866
|
+
throw new Error('peach motion capture needs a non-negative settleMs')
|
|
1867
1867
|
}
|
|
1868
1868
|
await page.evaluate(measureMotionChange, {
|
|
1869
1869
|
definition: MOTION_CHANGE_DEFINITION,
|
|
@@ -1943,7 +1943,7 @@ export const device = {
|
|
|
1943
1943
|
const live = captureWindow.SootSim?.bridges?.liveComposite
|
|
1944
1944
|
const lockstep = captureWindow.SootSim?.bridges?.lockstepCapture
|
|
1945
1945
|
if (!live || typeof live.captureFresh !== 'function') {
|
|
1946
|
-
throw new Error('
|
|
1946
|
+
throw new Error('peach live composite bridge is not installed')
|
|
1947
1947
|
}
|
|
1948
1948
|
if (!lockstep || typeof lockstep.begin !== 'function') {
|
|
1949
1949
|
throw new Error('SootSim lockstep capture bridge is not installed')
|
|
@@ -1959,12 +1959,12 @@ export const device = {
|
|
|
1959
1959
|
registry[input.token] = state
|
|
1960
1960
|
const measureChange = captureWindow.__sootsimMeasureMotionChange
|
|
1961
1961
|
if (!measureChange) {
|
|
1962
|
-
throw new Error('
|
|
1962
|
+
throw new Error('peach motion change definition is not installed')
|
|
1963
1963
|
}
|
|
1964
1964
|
|
|
1965
1965
|
const captureBitmap = async () => {
|
|
1966
1966
|
const { canvas } = await live.captureFresh()
|
|
1967
|
-
if (!canvas) throw new Error('
|
|
1967
|
+
if (!canvas) throw new Error('peach live composite produced no canvas')
|
|
1968
1968
|
return createImageBitmap(canvas)
|
|
1969
1969
|
}
|
|
1970
1970
|
const boundsFor = (bitmap: ImageBitmap) => {
|
|
@@ -2001,7 +2001,7 @@ export const device = {
|
|
|
2001
2001
|
canvas.width = bounds.width
|
|
2002
2002
|
canvas.height = bounds.height
|
|
2003
2003
|
const context = canvas.getContext('2d', { willReadFrequently: true })
|
|
2004
|
-
if (!context) throw new Error('
|
|
2004
|
+
if (!context) throw new Error('peach motion detector needs a 2d canvas')
|
|
2005
2005
|
context.drawImage(
|
|
2006
2006
|
bitmap,
|
|
2007
2007
|
bounds.left,
|
|
@@ -2020,7 +2020,7 @@ export const device = {
|
|
|
2020
2020
|
canvas.width = snapshot.bitmap.width
|
|
2021
2021
|
canvas.height = snapshot.bitmap.height
|
|
2022
2022
|
const context = canvas.getContext('2d')
|
|
2023
|
-
if (!context) throw new Error('
|
|
2023
|
+
if (!context) throw new Error('peach motion capture needs a 2d canvas')
|
|
2024
2024
|
context.drawImage(snapshot.bitmap, 0, 0)
|
|
2025
2025
|
snapshot.bitmap.close()
|
|
2026
2026
|
return {
|
|
@@ -2035,7 +2035,7 @@ export const device = {
|
|
|
2035
2035
|
|
|
2036
2036
|
const interact = captureWindow.SootSim?.bridges?.interact
|
|
2037
2037
|
if (input.hold && (!interact || typeof interact.touchDown !== 'function')) {
|
|
2038
|
-
throw new Error('
|
|
2038
|
+
throw new Error('peach interact bridge is not installed')
|
|
2039
2039
|
}
|
|
2040
2040
|
const frameMs = 1000 / 60
|
|
2041
2041
|
const controller = await lockstep.begin(60)
|
|
@@ -2088,11 +2088,11 @@ export const device = {
|
|
|
2088
2088
|
if (input.hold && interact) {
|
|
2089
2089
|
const hit = await interact.touchDown(input.hold.x, input.hold.y)
|
|
2090
2090
|
if (!hit) {
|
|
2091
|
-
throw new Error(`
|
|
2091
|
+
throw new Error(`peach motion hold missed at ${input.hold.x},${input.hold.y}`)
|
|
2092
2092
|
}
|
|
2093
2093
|
} else {
|
|
2094
2094
|
while (!state.triggerCompleted) {
|
|
2095
|
-
if (state.cancelled) throw new Error('
|
|
2095
|
+
if (state.cancelled) throw new Error('peach motion capture was cancelled')
|
|
2096
2096
|
await new Promise((resolve) => setTimeout(resolve, 0))
|
|
2097
2097
|
}
|
|
2098
2098
|
}
|
|
@@ -2101,7 +2101,7 @@ export const device = {
|
|
|
2101
2101
|
let detectedMeasurement: MotionChangeMeasurement | null = null
|
|
2102
2102
|
const detectionFrameLimit = Math.ceil((input.detectionTimeoutMs * 60) / 1000)
|
|
2103
2103
|
for (let frame = 0; frame < detectionFrameLimit; frame++) {
|
|
2104
|
-
if (state.cancelled) throw new Error('
|
|
2104
|
+
if (state.cancelled) throw new Error('peach motion capture was cancelled')
|
|
2105
2105
|
const receipt = await controller.stepFrame()
|
|
2106
2106
|
await advanceHold(receipt)
|
|
2107
2107
|
const candidateBitmap = await captureBitmap()
|
|
@@ -2123,13 +2123,13 @@ export const device = {
|
|
|
2123
2123
|
}
|
|
2124
2124
|
if (!visibleStart || !detectedMeasurement) {
|
|
2125
2125
|
throw new Error(
|
|
2126
|
-
`
|
|
2126
|
+
`peach motion had no visible change before ${input.detectionTimeoutMs}ms`,
|
|
2127
2127
|
)
|
|
2128
2128
|
}
|
|
2129
2129
|
|
|
2130
2130
|
const snapshots: Snapshot[] = []
|
|
2131
2131
|
for (const stage of input.stages) {
|
|
2132
|
-
if (state.cancelled) throw new Error('
|
|
2132
|
+
if (state.cancelled) throw new Error('peach motion capture was cancelled')
|
|
2133
2133
|
// step through every hold move and the release that fall before
|
|
2134
2134
|
// this stage one frame at a time, so the stage paints the pointer
|
|
2135
2135
|
// where it belongs rather than a hold the jump skipped past.
|
|
@@ -2211,7 +2211,7 @@ export const device = {
|
|
|
2211
2211
|
try {
|
|
2212
2212
|
if (!options.hold) {
|
|
2213
2213
|
if (typeof options.trigger !== 'function') {
|
|
2214
|
-
throw new Error('
|
|
2214
|
+
throw new Error('peach motion capture needs a trigger or a hold')
|
|
2215
2215
|
}
|
|
2216
2216
|
await Promise.resolve(options.trigger())
|
|
2217
2217
|
}
|
|
@@ -2226,7 +2226,7 @@ export const device = {
|
|
|
2226
2226
|
}
|
|
2227
2227
|
).__sootsimVisibleChangeCaptures
|
|
2228
2228
|
const capture = registry?.[captureToken]
|
|
2229
|
-
if (!capture) throw new Error('
|
|
2229
|
+
if (!capture) throw new Error('peach motion capture disarmed before trigger')
|
|
2230
2230
|
capture.triggerCompleted = true
|
|
2231
2231
|
}, token)
|
|
2232
2232
|
const capture = await capturePromise
|
|
@@ -2331,7 +2331,7 @@ export const device = {
|
|
|
2331
2331
|
const screenshot = captureWindow.SootSim?.bridges?.screenshot
|
|
2332
2332
|
const live = captureWindow.SootSim?.bridges?.liveComposite
|
|
2333
2333
|
if (typeof screenshot !== 'function') {
|
|
2334
|
-
throw new Error('
|
|
2334
|
+
throw new Error('peach screenshot bridge is not installed')
|
|
2335
2335
|
}
|
|
2336
2336
|
const registry =
|
|
2337
2337
|
captureWindow.__sootsimTimedCaptures ??
|
|
@@ -2353,7 +2353,7 @@ export const device = {
|
|
|
2353
2353
|
}
|
|
2354
2354
|
state.ready = true
|
|
2355
2355
|
while (state.anchorPerformanceMs === null || state.anchorWallMs === null) {
|
|
2356
|
-
if (state.cancelled) throw new Error('
|
|
2356
|
+
if (state.cancelled) throw new Error('peach timed capture was cancelled')
|
|
2357
2357
|
await new Promise((resolve) => setTimeout(resolve, 0))
|
|
2358
2358
|
}
|
|
2359
2359
|
const captureAnchorMs = state.anchorWallMs
|
|
@@ -2481,7 +2481,7 @@ export const device = {
|
|
|
2481
2481
|
}
|
|
2482
2482
|
).__sootsimTimedCaptures
|
|
2483
2483
|
const capture = registry?.[captureToken]
|
|
2484
|
-
if (!capture?.ready) throw new Error('
|
|
2484
|
+
if (!capture?.ready) throw new Error('peach timed capture was not armed')
|
|
2485
2485
|
const nowMs = Date.now()
|
|
2486
2486
|
capture.anchorWallMs = anchorMs ?? nowMs
|
|
2487
2487
|
capture.anchorPerformanceMs = performance.now() - (nowMs - capture.anchorWallMs)
|
|
@@ -2563,7 +2563,7 @@ export const device = {
|
|
|
2563
2563
|
| ((opts?: unknown) => Promise<string>)
|
|
2564
2564
|
| undefined
|
|
2565
2565
|
if (typeof screenshot !== 'function') {
|
|
2566
|
-
throw new Error('
|
|
2566
|
+
throw new Error('peach screenshot bridge is not installed')
|
|
2567
2567
|
}
|
|
2568
2568
|
const start = Date.now()
|
|
2569
2569
|
const out: Array<{
|
package/detox/navigation.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import { by, device, element, waitFor } from './index'
|
|
5
5
|
|
|
6
|
-
const BASE_URL = process.env.
|
|
6
|
+
const BASE_URL = process.env.PEACH_URL || 'http://localhost:5173'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* navigate to a kitchen-sink test case in sootsim
|
|
@@ -17,7 +17,7 @@ export async function navigateToTestCase(
|
|
|
17
17
|
|
|
18
18
|
// navigate to the test case directly via URL, preserving any params
|
|
19
19
|
// already on BASE_URL (device=, colorScheme=, etc.) — the conformance
|
|
20
|
-
// runner sets these via
|
|
20
|
+
// runner sets these via PEACH_URL and dropping them silently rendered
|
|
21
21
|
// pro max at iphone 16 dimensions.
|
|
22
22
|
const target = new URL(BASE_URL)
|
|
23
23
|
target.searchParams.set('test', testCaseName)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.573 | (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;
|
|
@@ -53,11 +53,11 @@ var import_node_path = require("node:path");
|
|
|
53
53
|
var import_node_url = require("node:url");
|
|
54
54
|
|
|
55
55
|
// src/public-brand.ts
|
|
56
|
-
var name = "
|
|
56
|
+
var name = "Peach";
|
|
57
57
|
var rnxPublicBrand = Object.freeze({
|
|
58
58
|
name,
|
|
59
59
|
packageName: "peachsim",
|
|
60
|
-
commandName: "
|
|
60
|
+
commandName: "peach",
|
|
61
61
|
domain: "rnxsim.com",
|
|
62
62
|
origin: "https://rnxsim.com"
|
|
63
63
|
});
|
|
@@ -106,7 +106,7 @@ function isSootsimDevCheckout() {
|
|
|
106
106
|
if (!argv1) return false;
|
|
107
107
|
try {
|
|
108
108
|
const real = import_node_fs2.default.realpathSync(argv1);
|
|
109
|
-
return real.includes(`${import_node_path2.default.sep}packages${import_node_path2.default.sep}
|
|
109
|
+
return real.includes(`${import_node_path2.default.sep}packages${import_node_path2.default.sep}peachsim${import_node_path2.default.sep}`);
|
|
110
110
|
} catch {
|
|
111
111
|
return false;
|
|
112
112
|
}
|
|
@@ -125,8 +125,8 @@ var COST_HISTORY_MAX_AGE_MS = 14 * 24 * 60 * 60 * 1e3;
|
|
|
125
125
|
|
|
126
126
|
// src/agent-sessions.ts
|
|
127
127
|
function resolveSootsimInvocation() {
|
|
128
|
-
if (process.env.
|
|
129
|
-
return { executable: process.env.
|
|
128
|
+
if (process.env.PEACH_BIN) {
|
|
129
|
+
return { executable: process.env.PEACH_BIN, prefixArgs: [] };
|
|
130
130
|
}
|
|
131
131
|
if (IS_STANDALONE) return rnxSelfInvocation();
|
|
132
132
|
if (process.versions.electron) {
|
|
@@ -148,14 +148,14 @@ function resolveSootsimInvocation() {
|
|
|
148
148
|
return { executable: process.argv[0], prefixArgs: [argv1] };
|
|
149
149
|
}
|
|
150
150
|
throw new Error(
|
|
151
|
-
"
|
|
151
|
+
"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`."
|
|
152
152
|
);
|
|
153
153
|
}
|
|
154
154
|
function tryWorkspaceSootsim() {
|
|
155
155
|
try {
|
|
156
156
|
const sootsimDir = resolveSootsimPackageDir();
|
|
157
157
|
if (!sootsimDir) return null;
|
|
158
|
-
const binaryName = `
|
|
158
|
+
const binaryName = `peach-${process.platform === "win32" ? "windows" : process.platform}-${process.arch}${process.platform === "win32" ? ".exe" : ""}`;
|
|
159
159
|
const distBinary = import_node_path3.default.join(sootsimDir, "dist-bin", binaryName);
|
|
160
160
|
if (import_node_fs3.default.existsSync(distBinary)) return { executable: distBinary, prefixArgs: [] };
|
|
161
161
|
const distBin = import_node_path3.default.join(sootsimDir, "dist-cli", "bin.js");
|
|
@@ -167,7 +167,7 @@ function tryWorkspaceSootsim() {
|
|
|
167
167
|
const buildMtime = import_node_fs3.default.statSync(distBin).mtimeMs;
|
|
168
168
|
if (buildMtime < srcMtime) {
|
|
169
169
|
console.warn(
|
|
170
|
-
`[
|
|
170
|
+
`[peach] dist-cli/bin.js is older than agent-wrapper.ts \u2014 rebuild with \`bun run --cwd packages/peachsim build:cli\`.`
|
|
171
171
|
);
|
|
172
172
|
}
|
|
173
173
|
}
|
|
@@ -251,7 +251,7 @@ var AgentDaemonClient = class {
|
|
|
251
251
|
this.ws.off("open", onOpen);
|
|
252
252
|
reject(
|
|
253
253
|
new AgentDaemonError(
|
|
254
|
-
`could not connect to
|
|
254
|
+
`could not connect to peach daemon on port ${this.port}: ${err.message}`,
|
|
255
255
|
"NO_DAEMON"
|
|
256
256
|
)
|
|
257
257
|
);
|
|
@@ -452,7 +452,7 @@ async function ensureDaemonRunning(opts = {}) {
|
|
|
452
452
|
}
|
|
453
453
|
if (shouldSkipPersistentDaemon()) {
|
|
454
454
|
throw new AgentDaemonError(
|
|
455
|
-
`no
|
|
455
|
+
`no peach bridge on port ${port}. run \`peach daemon install\` to enable the faster background service, or \`peach serve\` in another shell.`,
|
|
456
456
|
"DEV_HOST_REFUSED"
|
|
457
457
|
);
|
|
458
458
|
}
|
|
@@ -474,7 +474,7 @@ async function ensureDaemonRunning(opts = {}) {
|
|
|
474
474
|
await new Promise((r) => setTimeout(r, 100));
|
|
475
475
|
}
|
|
476
476
|
throw new AgentDaemonError(
|
|
477
|
-
`spawned
|
|
477
|
+
`spawned peach daemon on port ${port} but it did not come up in time. run \`peach serve\` manually to diagnose.`,
|
|
478
478
|
"SPAWN_TIMEOUT"
|
|
479
479
|
);
|
|
480
480
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.573 | (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;
|