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/main.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// the
|
|
1
|
+
// the peach CLI proper: argv parsing, the one-time privacy choice, and the
|
|
2
2
|
// single lazy-imported command a run dispatches to. `./bin` imports this only
|
|
3
3
|
// when none of its hidden entry points claimed the process.
|
|
4
4
|
|
|
@@ -22,7 +22,7 @@ import { IS_STANDALONE } from './standalone'
|
|
|
22
22
|
// don't paper over real bugs.
|
|
23
23
|
function handleTopLevelError(err: unknown): never {
|
|
24
24
|
const msg = err instanceof Error ? err.message : String(err)
|
|
25
|
-
//
|
|
25
|
+
// peach's known top-level errors are all single-line, narrow strings.
|
|
26
26
|
// everything else gets the full stack so unexpected crashes still surface.
|
|
27
27
|
const isKnownCliFailure =
|
|
28
28
|
/^command timed out after \d+s$/.test(msg) ||
|
|
@@ -32,12 +32,12 @@ function handleTopLevelError(err: unknown): never {
|
|
|
32
32
|
msg.startsWith('saved sim ') ||
|
|
33
33
|
msg.startsWith('no sim connected with id ') ||
|
|
34
34
|
msg.startsWith('could not connect to ws://') ||
|
|
35
|
-
msg.startsWith('
|
|
36
|
-
msg.startsWith('
|
|
37
|
-
msg.startsWith('
|
|
35
|
+
msg.startsWith('peach bridge daemon is not running') ||
|
|
36
|
+
msg.startsWith('peach bridge lockfile is fresh') ||
|
|
37
|
+
msg.startsWith('peach bridge exited before becoming ready') ||
|
|
38
38
|
msg.startsWith(`${rnxPublicBrand.commandName} open: requested bridge port`) ||
|
|
39
39
|
msg.startsWith('background daemon setup is unavailable') ||
|
|
40
|
-
msg.startsWith('
|
|
40
|
+
msg.startsWith('peach bridge did not start within')
|
|
41
41
|
if (isKnownCliFailure && !process.env.SOOTSIM_VERBOSE) {
|
|
42
42
|
process.stderr.write(` ${msg}\n`)
|
|
43
43
|
process.exit(1)
|
|
@@ -191,7 +191,7 @@ async function scheduleAutomaticCliUpdate(exitCode: number): Promise<void> {
|
|
|
191
191
|
const update = takeCliUpdateNotification()
|
|
192
192
|
if (update) {
|
|
193
193
|
process.stderr.write(
|
|
194
|
-
` update:
|
|
194
|
+
` update: peach v${update.currentVersion} → v${update.latestVersion} · run \`peach upgrade\`\n`,
|
|
195
195
|
)
|
|
196
196
|
}
|
|
197
197
|
if (!claimAutomaticCliUpdateCheck()) return
|
|
@@ -223,7 +223,7 @@ if (parsed.version) {
|
|
|
223
223
|
console.log(`${rnxPublicBrand.commandName} v${getCliVersion()}${suffix}`)
|
|
224
224
|
// runtime version on its own line — keeps the first line parseable while
|
|
225
225
|
// surfacing the (independently-versioned) engine runtime users actually
|
|
226
|
-
// render with. see `
|
|
226
|
+
// render with. see `peach upgrade`.
|
|
227
227
|
const { readActiveRuntime } = await import('../src/home-paths')
|
|
228
228
|
const runtime = readActiveRuntime()
|
|
229
229
|
console.log(runtime ? `runtime v${runtime}` : 'runtime not installed')
|
|
@@ -270,7 +270,7 @@ if (!parsed.command && parsed.commandArgs.length === 0) {
|
|
|
270
270
|
}
|
|
271
271
|
|
|
272
272
|
// route to command. an empty command at this point only happens if the
|
|
273
|
-
// caller passed bare positional args without a verb (e.g. `
|
|
273
|
+
// caller passed bare positional args without a verb (e.g. `peach -- foo`),
|
|
274
274
|
// which used to fall through to the bundler-wrap behavior in `dev`. now that
|
|
275
275
|
// `dev` is gone, treat it as "show help".
|
|
276
276
|
const command = parsed.command ?? ''
|
|
@@ -313,8 +313,8 @@ if (
|
|
|
313
313
|
await exitWithFlush(await runReset(commandArgsWithSim, { port }))
|
|
314
314
|
}
|
|
315
315
|
// for grouping verbs, try to resolve per-verb help from the first
|
|
316
|
-
// positional arg. e.g. `
|
|
317
|
-
// not the generic `do` grouping page. bare `
|
|
316
|
+
// positional arg. e.g. `peach do tap --help` shows tap's help page,
|
|
317
|
+
// not the generic `do` grouping page. bare `peach do --help` falls
|
|
318
318
|
// through to runInspect which has the full verb group listing.
|
|
319
319
|
const isGroupingVerb =
|
|
320
320
|
command === 'do' ||
|
|
@@ -328,7 +328,7 @@ if (
|
|
|
328
328
|
// shell and perf subcommands are documented by their runtime dispatchers.
|
|
329
329
|
// don't try to route through generated per-verb docs.
|
|
330
330
|
} else if (isGroupingVerb && !subVerb) {
|
|
331
|
-
// bare `
|
|
331
|
+
// bare `peach <group> --help` — render from the registry.
|
|
332
332
|
const { printGroupHelp } = await import('./help')
|
|
333
333
|
if (printGroupHelp(command)) await exitWithFlush(0)
|
|
334
334
|
// fall through — runInspect shows the full help for anything the
|
|
@@ -390,7 +390,7 @@ try {
|
|
|
390
390
|
const { runMaestro } = await import('./commands/maestro')
|
|
391
391
|
// Maestro forwards playback argv to the shared runner, so it must
|
|
392
392
|
// receive the global `--sim`. passing the bare
|
|
393
|
-
// parsed.commandArgs dropped an explicit `
|
|
393
|
+
// parsed.commandArgs dropped an explicit `peach --sim <id> maestro
|
|
394
394
|
// …`, silently falling back to the current/saved sim (QA F21-4).
|
|
395
395
|
const code = await runMaestro(commandArgsWithSim, { port, verbose })
|
|
396
396
|
// bridge + dynamic imports leave handles open that keep node alive.
|
|
@@ -539,7 +539,7 @@ try {
|
|
|
539
539
|
case 'web': {
|
|
540
540
|
const { getRnxCommandAvailability } = await import('./command-registry')
|
|
541
541
|
const availability = getRnxCommandAvailability('web', parsed.commandArgs, 'node')
|
|
542
|
-
console.error(` ${availability.reason ?? '
|
|
542
|
+
console.error(` ${availability.reason ?? 'peach web is unavailable'}`)
|
|
543
543
|
await exitWithFlush(1)
|
|
544
544
|
}
|
|
545
545
|
|
|
@@ -82,7 +82,7 @@ export const OUTBOUND_ENDPOINTS: Record<string, OutboundEndpointDeclaration> = {
|
|
|
82
82
|
},
|
|
83
83
|
same_origin_runtime: {
|
|
84
84
|
category: 'same-origin-runtime',
|
|
85
|
-
destination: 'the origin already serving the
|
|
85
|
+
destination: 'the origin already serving the peach runtime',
|
|
86
86
|
preConsent: true,
|
|
87
87
|
payload: 'runtime assets and shared local settings',
|
|
88
88
|
},
|
|
@@ -90,7 +90,7 @@ export const OUTBOUND_ENDPOINTS: Record<string, OutboundEndpointDeclaration> = {
|
|
|
90
90
|
category: 'guest-app-network',
|
|
91
91
|
destination: 'URLs requested by the user app or supplied explicitly by the user',
|
|
92
92
|
preConsent: true,
|
|
93
|
-
payload: 'the app request itself;
|
|
93
|
+
payload: 'the app request itself; peach does not add telemetry fields',
|
|
94
94
|
},
|
|
95
95
|
remote_display_server: {
|
|
96
96
|
category: 'explicit-user-action',
|
|
@@ -109,10 +109,10 @@ export const OUTBOUND_ENDPOINTS: Record<string, OutboundEndpointDeclaration> = {
|
|
|
109
109
|
// the only egress that sends the CONTENTS of the user's project somewhere,
|
|
110
110
|
// and to an operator-chosen host rather than a Contrast one, so it must not
|
|
111
111
|
// be readable as "the usual Contrast call".
|
|
112
|
-
|
|
112
|
+
peach_cloud_box: {
|
|
113
113
|
category: 'explicit-user-action',
|
|
114
114
|
destination:
|
|
115
|
-
'the
|
|
115
|
+
'the Peach Cloud box service named by --endpoint or PEACH_BOX_ENDPOINT; no default, so this call cannot happen unless the user names a host',
|
|
116
116
|
preConsent: false,
|
|
117
117
|
payload:
|
|
118
118
|
'every file git reports for the current checkout, then shell commands and file reads and writes for as long as the box shell is open',
|
|
@@ -125,20 +125,20 @@ export const OUTBOUND_ENDPOINTS: Record<string, OutboundEndpointDeclaration> = {
|
|
|
125
125
|
payload:
|
|
126
126
|
'the project .swift sources, packed bundle resources and images, plus the signed preview token or ccdn_ api key that authorizes the compile',
|
|
127
127
|
},
|
|
128
|
-
|
|
128
|
+
peach_cloud_sim: {
|
|
129
129
|
category: 'explicit-user-action',
|
|
130
130
|
destination:
|
|
131
|
-
'https://rnxsim.com by default, or the test or disposable origin named by
|
|
131
|
+
'https://rnxsim.com by default, or the test or disposable origin named by PEACH_CLOUD_ORIGIN',
|
|
132
132
|
preConsent: false,
|
|
133
133
|
payload:
|
|
134
|
-
'the Metro JavaScript bundle selected by
|
|
134
|
+
'the Metro JavaScript bundle selected by peach ios --remote, then structured simulator commands and lifecycle requests',
|
|
135
135
|
},
|
|
136
136
|
tunnel_tool_download: {
|
|
137
137
|
category: 'explicit-user-action',
|
|
138
138
|
destination: 'https://github.com/cloudflare/cloudflared/releases/latest/download/',
|
|
139
139
|
preConsent: false,
|
|
140
140
|
payload:
|
|
141
|
-
'platform and architecture only, carried in the release asset name; fires only for
|
|
141
|
+
'platform and architecture only, carried in the release asset name; fires only for peach test --cloud with a live dev stack when no cloudflared binary is installed',
|
|
142
142
|
},
|
|
143
143
|
}
|
|
144
144
|
|
|
@@ -152,50 +152,50 @@ export interface OutboundCallDeclaration {
|
|
|
152
152
|
// fails the package test until its destination and consent behavior are declared.
|
|
153
153
|
export const DECLARED_OUTBOUND_CALLS: Record<string, OutboundCallDeclaration> = {
|
|
154
154
|
'packages/peachsim/cli/cloud-client.ts :: fetch :: `${apiOrigin}/v1/boxes`': {
|
|
155
|
-
category: '
|
|
155
|
+
category: 'peach_cloud_sim',
|
|
156
156
|
count: 1,
|
|
157
157
|
},
|
|
158
158
|
'packages/peachsim/cli/cloud-client.ts :: fetch :: `${session.apiOrigin}/v1/sims/${encodeURIComponent()}/claim`':
|
|
159
|
-
{ category: '
|
|
159
|
+
{ category: 'peach_cloud_sim', count: 1 },
|
|
160
160
|
// two call sites delete a box by id: closing a nano-box simulator, and
|
|
161
161
|
// closing a box from a session that is not itself the box. one destination,
|
|
162
162
|
// so one declaration.
|
|
163
163
|
'packages/peachsim/cli/cloud-client.ts :: fetch :: `${session.apiOrigin}/v1/boxes/${encodeURIComponent()}`':
|
|
164
|
-
{ category: '
|
|
164
|
+
{ category: 'peach_cloud_sim', count: 2 },
|
|
165
165
|
// closing an instance simulator deletes it by its own id with its own token.
|
|
166
166
|
'packages/peachsim/cli/cloud-client.ts :: fetch :: `${session.apiOrigin}/v1/sims/${encodeURIComponent()}`':
|
|
167
|
-
{ category: '
|
|
167
|
+
{ category: 'peach_cloud_sim', count: 1 },
|
|
168
168
|
// the box api mirrors the sim api for a micro box: the same destination and
|
|
169
169
|
// the same box token, reached through the session rather than a loose id.
|
|
170
170
|
// driving a box sends each command to its own box.
|
|
171
171
|
'packages/peachsim/cli/cloud-client.ts :: fetch :: `${this.session.apiOrigin}/v1/boxes/${encodeURIComponent()}/commands`':
|
|
172
|
-
{ category: '
|
|
172
|
+
{ category: 'peach_cloud_sim', count: 1 },
|
|
173
173
|
// stopping a box leaves it allocated, unlike the delete above.
|
|
174
174
|
'packages/peachsim/cli/cloud-client.ts :: fetch :: `${session.apiOrigin}/v1/boxes/${encodeURIComponent()}/stop`':
|
|
175
|
-
{ category: '
|
|
175
|
+
{ category: 'peach_cloud_sim', count: 1 },
|
|
176
176
|
// the display grant is polled until the box hands one back; the body is
|
|
177
177
|
// empty, so the request carries no project or app data.
|
|
178
178
|
'packages/peachsim/cli/cloud-client.ts :: fetch :: `${options.apiOrigin}/v1/boxes/${encodeURIComponent()}/display-grant`':
|
|
179
|
-
{ category: '
|
|
180
|
-
// `
|
|
179
|
+
{ category: 'peach_cloud_sim', count: 1 },
|
|
180
|
+
// `peach remote` creates through the instance api and lists what it made.
|
|
181
181
|
// the create carries labels and wait=true in the query; the list filters
|
|
182
182
|
// by the remote label.
|
|
183
183
|
'packages/peachsim/cli/cloud-client.ts :: fetch :: `${apiOrigin}/v1/sims?${query}`': {
|
|
184
|
-
category: '
|
|
184
|
+
category: 'peach_cloud_sim',
|
|
185
185
|
count: 1,
|
|
186
186
|
},
|
|
187
187
|
'packages/peachsim/cli/cloud-client.ts :: fetch :: `${apiOrigin}/v1/sims?${selector}`':
|
|
188
188
|
{
|
|
189
|
-
category: '
|
|
189
|
+
category: 'peach_cloud_sim',
|
|
190
190
|
count: 1,
|
|
191
191
|
},
|
|
192
192
|
// rereading one simulator and deleting one by id share the route: the
|
|
193
|
-
// reattach probe reads with either credential and `
|
|
193
|
+
// reattach probe reads with either credential and `peach remote stop`
|
|
194
194
|
// deletes with the account credential.
|
|
195
195
|
'packages/peachsim/cli/cloud-client.ts :: fetch :: `${apiOrigin}/v1/sims/${encodeURIComponent()}`':
|
|
196
|
-
{ category: '
|
|
196
|
+
{ category: 'peach_cloud_sim', count: 2 },
|
|
197
197
|
'packages/peachsim/cli/cloud-client.ts :: fetch :: `${this.session.apiOrigin}/v1/sims/${encodeURIComponent()}/commands`':
|
|
198
|
-
{ category: '
|
|
198
|
+
{ category: 'peach_cloud_sim', count: 1 },
|
|
199
199
|
'packages/peachsim/cli/cloud-client.ts :: fetch :: bundleUrl': {
|
|
200
200
|
category: 'guest_app_network',
|
|
201
201
|
count: 1,
|
|
@@ -225,7 +225,7 @@ export const DECLARED_OUTBOUND_CALLS: Record<string, OutboundCallDeclaration> =
|
|
|
225
225
|
count: 1,
|
|
226
226
|
},
|
|
227
227
|
'packages/peachsim/src/cloud.ts :: fetch :: url': {
|
|
228
|
-
category: '
|
|
228
|
+
category: 'peach_cloud_sim',
|
|
229
229
|
count: 1,
|
|
230
230
|
},
|
|
231
231
|
// maestro's flow `http` API. the url is whatever the flow author wrote, and
|
|
@@ -234,15 +234,15 @@ export const DECLARED_OUTBOUND_CALLS: Record<string, OutboundCallDeclaration> =
|
|
|
234
234
|
category: 'guest_app_network',
|
|
235
235
|
count: 1,
|
|
236
236
|
},
|
|
237
|
-
// `
|
|
237
|
+
// `peach box create` uploads the checkout to the box service and then talks to
|
|
238
238
|
// it. the destination is whatever the user named; there is no default.
|
|
239
239
|
'packages/peach-cloud-box/src/client.ts :: fetch :: endpointOf(base, name, verb, search)':
|
|
240
240
|
{
|
|
241
|
-
category: '
|
|
241
|
+
category: 'peach_cloud_box',
|
|
242
242
|
count: 1,
|
|
243
243
|
},
|
|
244
244
|
'packages/peach-cloud-box/src/client.ts :: websocket :: url': {
|
|
245
|
-
category: '
|
|
245
|
+
category: 'peach_cloud_box',
|
|
246
246
|
count: 1,
|
|
247
247
|
},
|
|
248
248
|
// a micro box's own Browser Run session, over the worker's BROWSER binding.
|
|
@@ -250,13 +250,13 @@ export const DECLARED_OUTBOUND_CALLS: Record<string, OutboundCallDeclaration> =
|
|
|
250
250
|
// is a placeholder that exists only so URL can parse the search parameters.
|
|
251
251
|
// nothing leaves Cloudflare and no project content is sent.
|
|
252
252
|
'packages/peach-cloud-box/src/browser-run.ts :: fetch :: sessionEndpoint(undefined, { keepAliveMs, includeTargets: true })':
|
|
253
|
-
{ category: '
|
|
253
|
+
{ category: 'peach_cloud_box', count: 1 },
|
|
254
254
|
'packages/peach-cloud-box/src/browser-run.ts :: fetch :: `https://browser.invalid/v1/devtools/browser/${sessionId}/json/list`':
|
|
255
|
-
{ category: '
|
|
255
|
+
{ category: 'peach_cloud_box', count: 1 },
|
|
256
256
|
// twice: closing the session, and the CDP websocket upgrade that navigates a
|
|
257
257
|
// target. both address the same session over the same binding.
|
|
258
258
|
'packages/peach-cloud-box/src/browser-run.ts :: fetch :: `https://browser.invalid/v1/devtools/browser/${sessionId}`':
|
|
259
|
-
{ category: '
|
|
259
|
+
{ category: 'peach_cloud_box', count: 2 },
|
|
260
260
|
// the account's own session meter: starting, listing and heartbeating the
|
|
261
261
|
// session a cloud box is billed against. no project content.
|
|
262
262
|
"packages/peach-cloud-box/src/client.ts :: fetch :: `${options.apiOrigin.replace(/\\/+$/, '')}/api/v1/rnx/sessions${ options.accountId ? `?accountId=${encodeURIComponent()}` : '' }`":
|
|
@@ -265,7 +265,7 @@ export const DECLARED_OUTBOUND_CALLS: Record<string, OutboundCallDeclaration> =
|
|
|
265
265
|
category: 'contrast_user_action',
|
|
266
266
|
count: 1,
|
|
267
267
|
},
|
|
268
|
-
// `
|
|
268
|
+
// `peach box connect` asks the account service which box that ID or name is
|
|
269
269
|
// and for the box's own token. the account is the only thing that knows, so
|
|
270
270
|
// this is the one call that turns a name into an authorized Box reference.
|
|
271
271
|
'packages/peach-cloud-box/src/client.ts :: fetch :: connectUrl': {
|
|
@@ -406,7 +406,7 @@ export const DECLARED_OUTBOUND_CALLS: Record<string, OutboundCallDeclaration> =
|
|
|
406
406
|
count: 2,
|
|
407
407
|
},
|
|
408
408
|
// the path is a parameter so one uploader serves both callers: recordings use
|
|
409
|
-
// /api/preview/upload/{init,finalize} (the default) and `
|
|
409
|
+
// /api/preview/upload/{init,finalize} (the default) and `peach preview` passes
|
|
410
410
|
// /api/v1/previews{,/finalize}. both are first-party contrast endpoints.
|
|
411
411
|
'packages/peach-engine/src/preview/presigned-upload.ts :: fetch :: `${origin}${endpoints.finalize}`':
|
|
412
412
|
{ category: 'contrast_user_action', count: 1 },
|
package/cli/parse-args.ts
CHANGED
|
@@ -35,7 +35,7 @@ const GLOBAL_FLAGS: Record<
|
|
|
35
35
|
// whether it takes a value. a command that rejects unknown flags uses this to
|
|
36
36
|
// tell a genuinely unknown flag apart from a global one typed after the
|
|
37
37
|
// command, where nothing reads it, and to show how to pass that one: telling
|
|
38
|
-
// someone to write `
|
|
38
|
+
// someone to write `peach --verbose <value>` earns them a second error.
|
|
39
39
|
export const GLOBAL_FLAG_TAKES_VALUE: ReadonlyMap<string, boolean> = new Map(
|
|
40
40
|
Object.entries(GLOBAL_FLAGS).flatMap(([name, def]): [string, boolean][] => {
|
|
41
41
|
const takesValue = def.type !== 'boolean'
|
|
@@ -50,9 +50,9 @@ export const GLOBAL_FLAG_TAKES_VALUE: ReadonlyMap<string, boolean> = new Map(
|
|
|
50
50
|
|
|
51
51
|
// top-level verbs that route into runInspect. the surface is intentionally
|
|
52
52
|
// tiny — everything else lives under one of the grouping verbs:
|
|
53
|
-
// - `
|
|
54
|
-
// - `
|
|
55
|
-
// - `
|
|
53
|
+
// - `peach get <noun>` reads
|
|
54
|
+
// - `peach do <action>` writes
|
|
55
|
+
// - `peach debug <tool>` instrumentation (handled by runDebug)
|
|
56
56
|
// `describe` and `find` stay at root as the most common entrypoints.
|
|
57
57
|
// `list` stays at root because it's a sim-management read.
|
|
58
58
|
export const TOP_LEVEL_RUNTIME_COMMANDS = new Set([
|
|
@@ -67,9 +67,9 @@ export const TOP_LEVEL_RUNTIME_COMMANDS = new Set([
|
|
|
67
67
|
'shell',
|
|
68
68
|
])
|
|
69
69
|
|
|
70
|
-
// grouping verbs that take a sub-verb (`
|
|
71
|
-
// `
|
|
72
|
-
// form (`
|
|
70
|
+
// grouping verbs that take a sub-verb (`peach wait ready`,
|
|
71
|
+
// `peach do tap-id`). agents and humans very often type the hyphenated
|
|
72
|
+
// form (`peach wait-ready`, `peach do-tap-id`) — it reads as one
|
|
73
73
|
// command and matches the typed-tool names (rnx_wait_ready). bin.ts
|
|
74
74
|
// normalizes `<verb>-<rest>` → `<verb> <rest>` for these so the intuitive
|
|
75
75
|
// spelling just works instead of failing as "unknown command".
|
package/cli/privacy.ts
CHANGED
|
@@ -42,7 +42,7 @@ export async function ensurePrivacyChoice(options: {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
const allowed = await confirm(
|
|
45
|
-
'Share anonymous package incompatibilities and error classes to improve
|
|
45
|
+
'Share anonymous package incompatibilities and error classes to improve peach?',
|
|
46
46
|
false,
|
|
47
47
|
)
|
|
48
48
|
// the engine's historical analytics and crash transports carry broader
|
package/cli/recording-access.ts
CHANGED
|
@@ -24,7 +24,7 @@ async function billingOriginFor(auth: CliAuth, originOverride?: string): Promise
|
|
|
24
24
|
if (shared?.origin) {
|
|
25
25
|
return shared.origin.replace(/\/$/, '')
|
|
26
26
|
}
|
|
27
|
-
// api-key auth (
|
|
27
|
+
// api-key auth (PEACH_API_KEY) carries no origin.
|
|
28
28
|
// resolve it the same way the upload itself does — probe a local Contrast
|
|
29
29
|
// stack on :3000, else fall back to prod. this keeps the entitlement
|
|
30
30
|
// check pointed at the *same* origin the recording will upload to (the
|
|
@@ -42,7 +42,7 @@ export interface RecordingEntitlementOptions {
|
|
|
42
42
|
* origin stored in the shared desktop session. */
|
|
43
43
|
originOverride?: string
|
|
44
44
|
/** allow GitHub installation/action auth to record for pr preview uploads.
|
|
45
|
-
* this is intentionally opt-in so local `
|
|
45
|
+
* this is intentionally opt-in so local `peach record` stays tied to
|
|
46
46
|
* the user's paid/trial desktop entitlement. */
|
|
47
47
|
allowGitHubAuth?: boolean
|
|
48
48
|
}
|
|
@@ -54,10 +54,10 @@ export async function ensureCliRecordingEntitlement(
|
|
|
54
54
|
const auth = resolveCliAuth()
|
|
55
55
|
if (!auth) {
|
|
56
56
|
process.stderr.write(
|
|
57
|
-
`\n
|
|
57
|
+
`\n peach needs auth before it can check recording access.\n\n` +
|
|
58
58
|
` pick one:\n` +
|
|
59
|
-
` • run \`
|
|
60
|
-
` • set
|
|
59
|
+
` • run \`peach login\`\n` +
|
|
60
|
+
` • set PEACH_API_KEY=sk_rnx_... (recommended for CI)\n\n`,
|
|
61
61
|
)
|
|
62
62
|
rnxExit(1)
|
|
63
63
|
}
|
|
@@ -72,7 +72,7 @@ export async function ensureCliRecordingEntitlement(
|
|
|
72
72
|
})
|
|
73
73
|
} catch (error) {
|
|
74
74
|
process.stderr.write(
|
|
75
|
-
`\n
|
|
75
|
+
`\n peach couldn't verify recording access.\n` +
|
|
76
76
|
` ${error instanceof Error ? error.message : String(error)}\n\n`,
|
|
77
77
|
)
|
|
78
78
|
rnxExit(1)
|
|
@@ -80,8 +80,8 @@ export async function ensureCliRecordingEntitlement(
|
|
|
80
80
|
|
|
81
81
|
if (res.status === 401) {
|
|
82
82
|
process.stderr.write(
|
|
83
|
-
`\n
|
|
84
|
-
` sign in again for that origin, or provide a valid
|
|
83
|
+
`\n peach couldn't verify recording access with the current auth against ${billingOrigin}.\n` +
|
|
84
|
+
` sign in again for that origin, or provide a valid PEACH_API_KEY.\n\n`,
|
|
85
85
|
)
|
|
86
86
|
rnxExit(1)
|
|
87
87
|
}
|
|
@@ -89,7 +89,7 @@ export async function ensureCliRecordingEntitlement(
|
|
|
89
89
|
if (!res.ok) {
|
|
90
90
|
const text = await res.text().catch(() => '')
|
|
91
91
|
process.stderr.write(
|
|
92
|
-
`\n
|
|
92
|
+
`\n peach couldn't verify recording access (${res.status}).\n` +
|
|
93
93
|
` ${text || 'unexpected billing response'}\n\n`,
|
|
94
94
|
)
|
|
95
95
|
rnxExit(1)
|
|
@@ -100,7 +100,7 @@ export async function ensureCliRecordingEntitlement(
|
|
|
100
100
|
|
|
101
101
|
const plan = data.plan ?? 'free'
|
|
102
102
|
process.stderr.write(
|
|
103
|
-
`\n
|
|
103
|
+
`\n peach recording requires Personal, Team, or an active trial.\n` +
|
|
104
104
|
` current plan: ${plan}.\n` +
|
|
105
105
|
` free keeps basic 3d mode; the trial unlocks the full Personal surface.\n\n`,
|
|
106
106
|
)
|
package/cli/resolve-assets.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// resolve
|
|
1
|
+
// resolve peach's bundled assets (fonts, icons, sounds)
|
|
2
2
|
// regardless of how the package was installed (source checkout, npm install, bunx).
|
|
3
3
|
//
|
|
4
4
|
// uses import.meta.url to derive the package root, then checks both
|
|
@@ -48,7 +48,7 @@ export function resolveAssets(): SootSimAssets {
|
|
|
48
48
|
const soundsDir = resolve(publicDir, 'sounds')
|
|
49
49
|
|
|
50
50
|
if (!existsSync(fontsDir)) {
|
|
51
|
-
console.warn(`[
|
|
51
|
+
console.warn(`[peach] warning: fonts directory not found at ${fontsDir}`)
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
return {
|
package/cli/rnx-in-process.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// running
|
|
1
|
+
// running a peach command inside the calling process instead of spawning the CLI.
|
|
2
2
|
//
|
|
3
3
|
// the parse and the dispatch here are the CLI's own: parseRnxArgs, the command
|
|
4
4
|
// registry behind it, and the same per-command handlers main.ts reaches. what
|
|
@@ -17,7 +17,7 @@ import { type RnxRunResult, runRnx } from './run-rnx'
|
|
|
17
17
|
import type { ParsedBridgeCliArgs, WsBridge } from './ws-bridge'
|
|
18
18
|
|
|
19
19
|
// the verbs that reach a simulator through the bridge and nothing else. every
|
|
20
|
-
// other registered command needs the machine
|
|
20
|
+
// other registered command needs the machine peach is installed on: a device to
|
|
21
21
|
// boot, a browser to open, a credential store, the bridge daemon, or the local
|
|
22
22
|
// filesystem. `state` and `reset` sit outside runInspect but take the same
|
|
23
23
|
// bridge, so they belong here too.
|
|
@@ -48,9 +48,9 @@ export async function runRnxInProcess(
|
|
|
48
48
|
for (const warning of parsed.warnings) console.error(warning)
|
|
49
49
|
const command = parsed.command
|
|
50
50
|
if (!command || !IN_PROCESS_COMMANDS.has(command)) {
|
|
51
|
-
const named = command ? `
|
|
51
|
+
const named = command ? `peach ${command}` : 'peach'
|
|
52
52
|
console.error(
|
|
53
|
-
` ${named} is not available here; this
|
|
53
|
+
` ${named} is not available here; this peach drives a simulator and has no machine to run on. runs here: ${RUNNABLE}`,
|
|
54
54
|
)
|
|
55
55
|
return 1
|
|
56
56
|
}
|
|
@@ -62,7 +62,7 @@ export async function runRnxInProcess(
|
|
|
62
62
|
: parsed.commandArgs
|
|
63
63
|
if (commandArgs.includes('--then')) {
|
|
64
64
|
console.error(
|
|
65
|
-
'
|
|
65
|
+
' peach do --then is not available here; a chain runs against a sim connection rather than the bridge. run the actions one at a time.',
|
|
66
66
|
)
|
|
67
67
|
return 1
|
|
68
68
|
}
|
package/cli/run-registry.ts
CHANGED
|
@@ -100,7 +100,7 @@ export function resolveRunProvenance(): RunProvenance {
|
|
|
100
100
|
|
|
101
101
|
const branch = contrastBranch ?? gitOutput('git rev-parse --abbrev-ref HEAD')
|
|
102
102
|
// env slug wins when present; otherwise infer from the github remote so a
|
|
103
|
-
// a plain local `
|
|
103
|
+
// a plain local `peach maestro test --preview` still lands on its repo's dashboard.
|
|
104
104
|
const remote = envOwner ? null : ownerRepoFromGitRemote()
|
|
105
105
|
return {
|
|
106
106
|
owner: envOwner ?? remote?.owner ?? null,
|
package/cli/run-rnx-core.ts
CHANGED
|
@@ -69,7 +69,7 @@ export async function runRnxCore(
|
|
|
69
69
|
|
|
70
70
|
if (parsed.version) {
|
|
71
71
|
captured.writer.stderr(
|
|
72
|
-
'
|
|
72
|
+
'peach --version is unavailable in the browser backend; use the node backend.\n',
|
|
73
73
|
)
|
|
74
74
|
return result(captured, 1)
|
|
75
75
|
}
|
|
@@ -110,7 +110,7 @@ export async function runRnxCore(
|
|
|
110
110
|
options.backend.kind,
|
|
111
111
|
)
|
|
112
112
|
if (!availability.available) {
|
|
113
|
-
captured.writer.stderr(`${availability.reason ?? `
|
|
113
|
+
captured.writer.stderr(`${availability.reason ?? `peach ${command} is unavailable`}\n`)
|
|
114
114
|
return result(captured, 1)
|
|
115
115
|
}
|
|
116
116
|
|
|
@@ -142,7 +142,7 @@ export async function runRnxCore(
|
|
|
142
142
|
: error instanceof Error
|
|
143
143
|
? error.message
|
|
144
144
|
: String(error)
|
|
145
|
-
captured.writer.stderr(`
|
|
145
|
+
captured.writer.stderr(`peach: ${message}\n`)
|
|
146
146
|
return result(captured, 1)
|
|
147
147
|
}
|
|
148
148
|
}
|
package/cli/run-rnx.ts
CHANGED
package/cli/runtime-notes.ts
CHANGED
|
@@ -50,7 +50,7 @@ export function formatRuntimeReleaseNotes(
|
|
|
50
50
|
version: string,
|
|
51
51
|
entry: ChangelogEntry | null,
|
|
52
52
|
): string {
|
|
53
|
-
const lines = [`what's new in
|
|
53
|
+
const lines = [`what's new in peach engine v${version}:`]
|
|
54
54
|
if (!entry || entry.sections.length === 0) {
|
|
55
55
|
lines.push(` release notes are not available yet`)
|
|
56
56
|
} else {
|
package/cli/self-invocation.ts
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// a presence check cannot tell them apart. inside the compiled binary
|
|
12
12
|
// `process.argv[1]` is a path in bun's virtual filesystem (`/$bunfs/root/...`)
|
|
13
13
|
// that passes `existsSync` in-process, so every site that probed argv[1]
|
|
14
|
-
// re-invoked itself as `
|
|
14
|
+
// re-invoked itself as `peach <bunfs path> <command>` and the child died on
|
|
15
15
|
// `unknown command`. the build-time constant is the only honest signal.
|
|
16
16
|
|
|
17
17
|
import { existsSync } from 'node:fs'
|
package/cli/send-to-box.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// "send to box": the running local app becomes a nano cloud simulator.
|
|
2
2
|
//
|
|
3
3
|
// one function serves both callers. the rail button in the shell reaches it
|
|
4
|
-
// through the local daemon's `/__send-to-box` route, and `
|
|
4
|
+
// through the local daemon's `/__send-to-box` route, and `peach box send` calls
|
|
5
5
|
// it directly; both hand it a way to run a bridge command against the sim that
|
|
6
6
|
// is running the app, and both get the same simulator id and URL back.
|
|
7
7
|
|