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
|
@@ -33,7 +33,7 @@ export async function runFindSubcommand(opts: {
|
|
|
33
33
|
// ranked-tappable list — same data source as --pressable, but the
|
|
34
34
|
// output prioritises high-signal targets the agent likely wants to
|
|
35
35
|
// tap next (visible, has text or testID, has accessibilityLabel),
|
|
36
|
-
// and emits a copy-paste `
|
|
36
|
+
// and emits a copy-paste `peach do` command per row so the agent
|
|
37
37
|
// doesn't have to re-form a tap from raw fields.
|
|
38
38
|
const interactive = hasFlag('--interactive-targets') || hasFlag('--actions')
|
|
39
39
|
const bareText =
|
|
@@ -71,7 +71,7 @@ export async function runFindSubcommand(opts: {
|
|
|
71
71
|
if (jsonOut) {
|
|
72
72
|
if (mode === 'interactive-targets' && Array.isArray(result)) {
|
|
73
73
|
// include the `tap` command per row when emitting JSON for agents
|
|
74
|
-
// — the human renderer does the same. tooling that drives
|
|
74
|
+
// — the human renderer does the same. tooling that drives peach
|
|
75
75
|
// can pick the highest-scored entry and execute its `tap` field.
|
|
76
76
|
printJson(rankInteractive(result).map((n) => ({ ...n, tap: tapCommandForNode(n) })))
|
|
77
77
|
} else {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// `
|
|
1
|
+
// `peach get-layout` — bounding boxes for visible meaningful elements on the
|
|
2
2
|
// current screen. focused on the layout numbers a designer checks: on-screen
|
|
3
3
|
// box (x/y/w/h). pass --styling for computed borderRadius, per-side padding,
|
|
4
4
|
// fontSize, visual style fields, and native rendered text contrast. pass
|
|
@@ -30,7 +30,7 @@ export async function runGetLayoutSubcommand(opts: {
|
|
|
30
30
|
if (
|
|
31
31
|
styling &&
|
|
32
32
|
error instanceof Error &&
|
|
33
|
-
(error.message === 'unsupported
|
|
33
|
+
(error.message === 'unsupported Peach Cloud command type: evaluate' ||
|
|
34
34
|
error.message.includes('requires the debug scope'))
|
|
35
35
|
) {
|
|
36
36
|
throw new Error(
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// `
|
|
1
|
+
// `peach get keyboard` — prints the current iOS keyboard's full state.
|
|
2
2
|
//
|
|
3
3
|
// shows visibility, keyboardType, returnKeyType, autoCapitalize policy,
|
|
4
4
|
// active QWERTY sub-mode, shift + capsLock, and the mounted accessory bar
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// `
|
|
1
|
+
// `peach list` — connected sims, with the active one marked.
|
|
2
2
|
|
|
3
3
|
import { resolveDevCheckoutRuntimeRoot } from '../../../src/runtime-assets'
|
|
4
4
|
import { type BridgeSimInfo, formatLockOwner, type WsBridge } from '../../ws-bridge'
|
|
@@ -92,7 +92,7 @@ function summarizeSimUrl(url: string | undefined): string | null {
|
|
|
92
92
|
parsed.pathname === '/sootsim/' ||
|
|
93
93
|
parsed.pathname === '/sootsim'
|
|
94
94
|
) {
|
|
95
|
-
return 'embedded
|
|
95
|
+
return 'embedded peach'
|
|
96
96
|
}
|
|
97
97
|
return null
|
|
98
98
|
} catch {
|
|
@@ -146,8 +146,8 @@ function printConnectedSims(sims: BridgeSimInfo[], selectedId?: string) {
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
// classify which engine a sim is running so dev-vs-published is never ambiguous
|
|
149
|
-
// to agents or humans reading `
|
|
150
|
-
// :5173; the Contrast app embeds
|
|
149
|
+
// to agents or humans reading `peach list`. dev shell serves local source on
|
|
150
|
+
// :5173; the Contrast app embeds peach on :3000; the bridge/daemon and the
|
|
151
151
|
// /__soot plugin serve the active runtime dir — which, inside a dev checkout, is
|
|
152
152
|
// the fresh dev-stack build (resolveDevCheckoutRuntimeRoot mode boundary), not a
|
|
153
153
|
// published runtime. keep this label honest so it never says "published" while
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// `
|
|
1
|
+
// `peach get memory` / `peach debug memory` — per-worker live object
|
|
2
2
|
// counts (nodes registered, pictures, raster images, paragraphs, yoga wasm
|
|
3
3
|
// nodes), image-loader cache, and JS heaps. one-shot by default; --watch
|
|
4
4
|
// samples repeatedly and reports per-counter slope, which is the leak-RCA
|
|
@@ -5,7 +5,7 @@ import { isSimSemanticTree, type InspectBridge } from './core'
|
|
|
5
5
|
//
|
|
6
6
|
// pass `positional` from a verb whose positionals are x/y coordinates (tap,
|
|
7
7
|
// double-tap, long-press) and a bare non-numeric first positional reads as a
|
|
8
|
-
// testID: `
|
|
8
|
+
// testID: `peach do tap my-button` works like `do tap-id my-button` and like
|
|
9
9
|
// `do scroll <id>`, instead of failing with a usage line for the one verb an
|
|
10
10
|
// agent is most likely to reach for. a coordinate is always numeric, so there
|
|
11
11
|
// is nothing to disambiguate.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// `
|
|
1
|
+
// `peach get screens` — print the current navigation stack + shell state +
|
|
2
2
|
// any presented modal + keyboard. answers "what screen am I on?" without
|
|
3
3
|
// having to dump the whole tree or scrape screen-specific testIDs.
|
|
4
4
|
//
|
|
@@ -224,7 +224,7 @@ export interface ReloadReadyResult {
|
|
|
224
224
|
errors: number
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
-
// post-reload readiness is the same engine-owned condition as `
|
|
227
|
+
// post-reload readiness is the same engine-owned condition as `peach wait ready`.
|
|
228
228
|
// keeping reload on that primitive prevents another polling implementation
|
|
229
229
|
// from drifting on loading text, live frames, or tree stability.
|
|
230
230
|
export async function pollForReloadReady(
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// `
|
|
1
|
+
// `peach get tree` — pruned structured semantic tree, default depth 5.
|
|
2
2
|
|
|
3
3
|
import { formatSemanticTree, inspectTree, isSimSemanticTree } from './core'
|
|
4
4
|
import { printJson, wantsJson } from './shared'
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
//
|
|
1
|
+
// peach wait event — block until a semantic timeline event of the
|
|
2
2
|
// given kind appears, or timeout.
|
|
3
3
|
//
|
|
4
4
|
// usage:
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
5
|
+
// peach wait event <kind> [--max-ms 5000] [--since now|cursor]
|
|
6
|
+
// peach wait event fetch [--filter <substring>]
|
|
7
|
+
// peach wait event screen [--equals SignInPage]
|
|
8
8
|
//
|
|
9
9
|
// the existing wait family is layout-driven: `wait selector` polls
|
|
10
10
|
// for a testID, `wait idle` polls for rAF + animation settling,
|
|
@@ -111,7 +111,7 @@ function eventMatches(
|
|
|
111
111
|
export async function runWaitEventSubcommand(opts: WaitEventOptions): Promise<void> {
|
|
112
112
|
const { bridge, args, positional, inspectUsage } = opts
|
|
113
113
|
// positional shape after verb-prefix strip and stripBooleanFlags:
|
|
114
|
-
//
|
|
114
|
+
// peach wait event <kind> → ['event', '<kind>']
|
|
115
115
|
// so positional[1] is the kind.
|
|
116
116
|
const kind = positional[1]
|
|
117
117
|
if (!kind) {
|
package/cli/commands/inspect.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
//
|
|
2
|
-
// connects to the
|
|
1
|
+
// peach inspect — dump node tree, accessibility info, query nodes
|
|
2
|
+
// connects to the peach WS bridge (no Playwright)
|
|
3
3
|
|
|
4
4
|
import { getCliInspectVerbMeta } from '@peach/skills/cli'
|
|
5
5
|
import { renderCliCommandHelp, renderCliGroupHelp } from '@peach/skills/cli/renderers'
|
|
@@ -155,8 +155,8 @@ function formatNetworkDuration(ms: number | null): string {
|
|
|
155
155
|
function printRecoverHint(): void {
|
|
156
156
|
process.stderr.write(
|
|
157
157
|
` the sim is not responding. recover it with:\n` +
|
|
158
|
-
`
|
|
159
|
-
`
|
|
158
|
+
` peach close --sim <id> # force-close the wedged sim\n` +
|
|
159
|
+
` peach list # confirm it's gone\n`,
|
|
160
160
|
)
|
|
161
161
|
}
|
|
162
162
|
|
|
@@ -495,7 +495,7 @@ function printRenderProfile(worker: string, rp: Record<string, any> | undefined)
|
|
|
495
495
|
// pretty-print the shell frame profile payload (__sootsimShellPerf.stop()):
|
|
496
496
|
// per-painted-frame timing from the shell worker merged with the render
|
|
497
497
|
// profile counters. numbers arrive pre-rounded from the worker. also used by
|
|
498
|
-
// `
|
|
498
|
+
// `peach maestro test --profile`, which records the same payload.
|
|
499
499
|
export function printShellPerfReport(result: Record<string, any>) {
|
|
500
500
|
const fps = result.avgMs > 0 ? (1000 / result.avgMs).toFixed(1) : '?'
|
|
501
501
|
const jank = result.jank && typeof result.jank === 'object' ? result.jank : null
|
|
@@ -862,7 +862,7 @@ async function performCloudKeys(
|
|
|
862
862
|
if (result.ok) return
|
|
863
863
|
const failed = result.steps.find((step) => !step.ok)
|
|
864
864
|
console.error(
|
|
865
|
-
` ${actionLabel} failed: ${failed?.error ?? result.error ?? 'no text input had focus'}. focus an input first with
|
|
865
|
+
` ${actionLabel} failed: ${failed?.error ?? result.error ?? 'no text input had focus'}. focus an input first with peach do tap-id or peach do type-into.`,
|
|
866
866
|
)
|
|
867
867
|
rnxExit(1)
|
|
868
868
|
}
|
|
@@ -877,7 +877,7 @@ async function requireVisualKeyboard(bridge: WsBridge, actionLabel: string) {
|
|
|
877
877
|
rnxExit(1)
|
|
878
878
|
}
|
|
879
879
|
console.error(
|
|
880
|
-
` ${actionLabel} requires the iOS keyboard to be visible. focus an input first with
|
|
880
|
+
` ${actionLabel} requires the iOS keyboard to be visible. focus an input first with peach do tap-id/tap-text or peach do type-into.`,
|
|
881
881
|
)
|
|
882
882
|
rnxExit(1)
|
|
883
883
|
}
|
|
@@ -913,7 +913,7 @@ async function runShellVisualCommand(
|
|
|
913
913
|
code: `(async () => {
|
|
914
914
|
const toggleLock = window.SootSim?.bridges?.mainShell?.toggleLock
|
|
915
915
|
if (typeof toggleLock !== 'function') {
|
|
916
|
-
throw new Error('
|
|
916
|
+
throw new Error('peach mainShell.toggleLock bridge unavailable')
|
|
917
917
|
}
|
|
918
918
|
await toggleLock()
|
|
919
919
|
return { ok: true, action: 'lock' }
|
|
@@ -949,9 +949,9 @@ function keyCodeToVisualKey(code: string) {
|
|
|
949
949
|
}
|
|
950
950
|
|
|
951
951
|
function getInspectCommandName(subcommand: string, directSubcommand: string | null) {
|
|
952
|
-
if (directSubcommand === subcommand) return `
|
|
952
|
+
if (directSubcommand === subcommand) return `peach ${subcommand}`
|
|
953
953
|
const group = getCliInspectVerbMeta(subcommand)?.group
|
|
954
|
-
return group ? `
|
|
954
|
+
return group ? `peach ${group} ${subcommand}` : `peach ${subcommand}`
|
|
955
955
|
}
|
|
956
956
|
|
|
957
957
|
function getInspectUsage(
|
|
@@ -993,7 +993,7 @@ async function recordInspectAction(
|
|
|
993
993
|
'`maestro keep` commits one action at a time',
|
|
994
994
|
)
|
|
995
995
|
} else {
|
|
996
|
-
console.error(' draft: action pending — `
|
|
996
|
+
console.error(' draft: action pending — `peach maestro keep` to commit')
|
|
997
997
|
}
|
|
998
998
|
}
|
|
999
999
|
|
|
@@ -1056,9 +1056,9 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
1056
1056
|
// strip a leading grouping verb — `get`, `do`, and (when forwarded from
|
|
1057
1057
|
// runDebug) `debug`. these are organizational prefixes and shouldn't leak
|
|
1058
1058
|
// into subcommand dispatch. e.g.:
|
|
1059
|
-
//
|
|
1060
|
-
//
|
|
1061
|
-
//
|
|
1059
|
+
// peach get tree → effectiveArgs = ['tree']
|
|
1060
|
+
// peach do tap 100 200 → effectiveArgs = ['tap', '100', '200']
|
|
1061
|
+
// peach debug state shell → effectiveArgs = ['state', 'shell']
|
|
1062
1062
|
const verbPrefix =
|
|
1063
1063
|
args[0] === 'get' || args[0] === 'do' || args[0] === 'debug' || args[0] === 'wait'
|
|
1064
1064
|
? args[0]
|
|
@@ -1133,21 +1133,21 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
1133
1133
|
const topLevelCommand = isTopLevel ? effectiveArgs[0] : null
|
|
1134
1134
|
// a usage string has to name something the user can actually type. the
|
|
1135
1135
|
// registry knows which group each verb belongs to, so an unprefixed
|
|
1136
|
-
// invocation still renders `
|
|
1136
|
+
// invocation still renders `peach get tree` rather than a bare verb.
|
|
1137
1137
|
const inspectCommand = (name: string) => {
|
|
1138
1138
|
if (opts.internalPerfCommand && name === 'perf') {
|
|
1139
|
-
return `
|
|
1139
|
+
return `peach perf ${opts.internalPerfCommand}`
|
|
1140
1140
|
}
|
|
1141
|
-
if (isTopLevel && name === effectiveArgs[0]) return `
|
|
1141
|
+
if (isTopLevel && name === effectiveArgs[0]) return `peach ${name}`
|
|
1142
1142
|
const group = invocationPrefix ?? getCliInspectVerbMeta(name)?.group
|
|
1143
|
-
return group ? `
|
|
1143
|
+
return group ? `peach ${group} ${name}` : `peach ${name}`
|
|
1144
1144
|
}
|
|
1145
1145
|
const inspectUsage = (name: string, tail: string) =>
|
|
1146
1146
|
` usage: ${inspectCommand(name)}${tail ? ` ${tail}` : ''}`
|
|
1147
1147
|
|
|
1148
1148
|
if (!subcommand || args.includes('--help') || args.includes('-h')) {
|
|
1149
1149
|
// all help output comes from the registry in packages/peach-skills
|
|
1150
|
-
// so `
|
|
1150
|
+
// so `peach do --help`, `peach get --help`, the website docs, and
|
|
1151
1151
|
// the Contrast skill markdown stay in lock-step. a drift check in
|
|
1152
1152
|
// test/sootsimCliRegistry.test.ts fails CI if a verb lands without a
|
|
1153
1153
|
// matching registry entry.
|
|
@@ -1217,8 +1217,8 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
1217
1217
|
return
|
|
1218
1218
|
}
|
|
1219
1219
|
|
|
1220
|
-
// `
|
|
1221
|
-
// short-circuit here so users can discover drivers even when no
|
|
1220
|
+
// `peach list --drivers` — pure local registry view, no bridge needed.
|
|
1221
|
+
// short-circuit here so users can discover drivers even when no peach
|
|
1222
1222
|
// session is running.
|
|
1223
1223
|
if (
|
|
1224
1224
|
subcommand === 'list' &&
|
|
@@ -1327,7 +1327,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
1327
1327
|
// like a settled sim to the next read, and that read then hands out
|
|
1328
1328
|
// coordinates the screen is still animating away from.
|
|
1329
1329
|
process.stderr.write(
|
|
1330
|
-
` ⚠ auto-settle failed (${error instanceof Error ? error.message : String(error)}) — next command may see mid-animation state. use \`
|
|
1330
|
+
` ⚠ auto-settle failed (${error instanceof Error ? error.message : String(error)}) — next command may see mid-animation state. use \`peach do settle\` to retry.\n`,
|
|
1331
1331
|
)
|
|
1332
1332
|
}
|
|
1333
1333
|
return
|
|
@@ -1345,7 +1345,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
1345
1345
|
})
|
|
1346
1346
|
if (!settled) {
|
|
1347
1347
|
process.stderr.write(
|
|
1348
|
-
` ⚠ auto-wait timed out after ${elapsed ?? budgetMs}ms — next command may see mid-animation state. use \`
|
|
1348
|
+
` ⚠ auto-wait timed out after ${elapsed ?? budgetMs}ms — next command may see mid-animation state. use \`peach do settle\` for a longer wait.\n`,
|
|
1349
1349
|
)
|
|
1350
1350
|
}
|
|
1351
1351
|
} catch {
|
|
@@ -1360,7 +1360,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
1360
1360
|
` tap failed: ${label} resolved to (${Math.round(x)},${Math.round(y)}), outside the ${screen?.width}x${screen?.height} screen`,
|
|
1361
1361
|
)
|
|
1362
1362
|
console.error(
|
|
1363
|
-
' the node exists but is scrolled out of view — scroll it on-screen first (
|
|
1363
|
+
' the node exists but is scrolled out of view — scroll it on-screen first (peach do scroll / swipe), then tap.',
|
|
1364
1364
|
)
|
|
1365
1365
|
return
|
|
1366
1366
|
}
|
|
@@ -1594,7 +1594,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
1594
1594
|
if (!seen.has(kind) && n) parts.push(`${n} ${kind}${n === 1 ? '' : 's'}`)
|
|
1595
1595
|
}
|
|
1596
1596
|
if (parts.length === 0) return
|
|
1597
|
-
console.error(`\n since last: ${parts.join(' · ')} —
|
|
1597
|
+
console.error(`\n since last: ${parts.join(' · ')} — peach what-happened`)
|
|
1598
1598
|
// advance cursor so the next CLI call only sees *new* events.
|
|
1599
1599
|
if (payload.summary.lastAt) {
|
|
1600
1600
|
try {
|
|
@@ -1660,7 +1660,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
1660
1660
|
const verboseTransitions =
|
|
1661
1661
|
(args.includes('--verbose') || args.includes('-v')) && !args.includes('--json')
|
|
1662
1662
|
if (invocationPrefix === 'do' && subcommand === 'shell') {
|
|
1663
|
-
console.error(' `
|
|
1663
|
+
console.error(' `peach do shell` was removed. use `peach shell ...` instead.')
|
|
1664
1664
|
rnxExit(1)
|
|
1665
1665
|
}
|
|
1666
1666
|
if (writeCommands.has(subcommand)) {
|
|
@@ -1797,9 +1797,9 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
1797
1797
|
}
|
|
1798
1798
|
|
|
1799
1799
|
case 'event': {
|
|
1800
|
-
//
|
|
1800
|
+
// peach wait event <kind> — timeline-backed wait. delegates
|
|
1801
1801
|
// matcher + polling to runWaitEventSubcommand so the same
|
|
1802
|
-
// logic is reachable from `
|
|
1802
|
+
// logic is reachable from `peach wait event` regardless of
|
|
1803
1803
|
// verb-group prefix (and the same shape is testable on its
|
|
1804
1804
|
// own).
|
|
1805
1805
|
await runWaitEventSubcommand({ bridge, args, positional, inspectUsage })
|
|
@@ -1808,7 +1808,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
1808
1808
|
|
|
1809
1809
|
case 'layout': {
|
|
1810
1810
|
const id = positional[1]
|
|
1811
|
-
// bare `
|
|
1811
|
+
// bare `peach get layout` (no id) measures visible elements on the
|
|
1812
1812
|
// screen by bounding box. --styling opts into box-model/style detail via
|
|
1813
1813
|
// the shared get-layout kernel the agent's app_get_layout also uses.
|
|
1814
1814
|
// passing an id keeps the single-node {x, y, width, height} lookup.
|
|
@@ -1844,7 +1844,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
1844
1844
|
case 'capture':
|
|
1845
1845
|
case 'screenshot': {
|
|
1846
1846
|
const outputArg = args.find((_, i) => args[i - 1] === '--output')
|
|
1847
|
-
const outputPath = outputArg || '/tmp/
|
|
1847
|
+
const outputPath = outputArg || '/tmp/peach-inspect.png'
|
|
1848
1848
|
const rect = await resolveSampleRect(args, bridge)
|
|
1849
1849
|
|
|
1850
1850
|
const request: { type: 'screenshot'; crop?: SampleRect } = { type: 'screenshot' }
|
|
@@ -1870,7 +1870,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
1870
1870
|
),
|
|
1871
1871
|
)
|
|
1872
1872
|
console.error(
|
|
1873
|
-
' samples an averaged color from the canvas. coords are logical
|
|
1873
|
+
' samples an averaged color from the canvas. coords are logical peach units.',
|
|
1874
1874
|
)
|
|
1875
1875
|
rnxExit(1)
|
|
1876
1876
|
}
|
|
@@ -2255,7 +2255,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
2255
2255
|
const payload = outcome.payload
|
|
2256
2256
|
|
|
2257
2257
|
if (payload?.error === 'bridge-not-ready') {
|
|
2258
|
-
console.error('
|
|
2258
|
+
console.error(' peach test bridge not ready')
|
|
2259
2259
|
rnxExit(1)
|
|
2260
2260
|
}
|
|
2261
2261
|
|
|
@@ -2366,7 +2366,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
2366
2366
|
}
|
|
2367
2367
|
|
|
2368
2368
|
case 'tap-best': {
|
|
2369
|
-
//
|
|
2369
|
+
// peach do tap-best <query> — try tap-id, then tap-text. the
|
|
2370
2370
|
// common agent ergonomic problem: the agent has a label like
|
|
2371
2371
|
// "Create expense" and doesn't know whether that's a testID
|
|
2372
2372
|
// or visible text. with tap-text it fails when the only
|
|
@@ -2402,7 +2402,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
2402
2402
|
| null
|
|
2403
2403
|
if (!payload) {
|
|
2404
2404
|
console.error(
|
|
2405
|
-
` tap-best: no testID or visible text matched "${query}". try \`
|
|
2405
|
+
` tap-best: no testID or visible text matched "${query}". try \`peach find --interactive-targets\` to list candidates.`,
|
|
2406
2406
|
)
|
|
2407
2407
|
rnxExit(1)
|
|
2408
2408
|
}
|
|
@@ -2412,7 +2412,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
2412
2412
|
}
|
|
2413
2413
|
if (payload.strategy === 'none') {
|
|
2414
2414
|
console.error(
|
|
2415
|
-
` tap-best: no testID or visible text matched "${query}". try \`
|
|
2415
|
+
` tap-best: no testID or visible text matched "${query}". try \`peach find --interactive-targets\` to list candidates.`,
|
|
2416
2416
|
)
|
|
2417
2417
|
rnxExit(1)
|
|
2418
2418
|
}
|
|
@@ -3102,8 +3102,8 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
3102
3102
|
|
|
3103
3103
|
case 'state': {
|
|
3104
3104
|
const stateCmd = positional[1]
|
|
3105
|
-
// `
|
|
3106
|
-
// `
|
|
3105
|
+
// `peach get state` (no sub-arg) → compact runtime dashboard.
|
|
3106
|
+
// `peach debug state <kind>` continues to dispatch the raw dumps.
|
|
3107
3107
|
if (verbPrefix === 'get' && !stateCmd) {
|
|
3108
3108
|
const base = await callTestBridge<Record<string, any>>(
|
|
3109
3109
|
bridge,
|
|
@@ -3512,14 +3512,14 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
3512
3512
|
|
|
3513
3513
|
case 'reload': {
|
|
3514
3514
|
// a cloud simulator is a headless runtime with no page to reload, and
|
|
3515
|
-
//
|
|
3515
|
+
// peach itself runs inside the box's workerd isolate rather than a node
|
|
3516
3516
|
// process, so the full-page branch below cannot work: it reconnects
|
|
3517
3517
|
// through `waitForBridgeConnected`, whose `createBridge` constructs the
|
|
3518
3518
|
// `ws` package's WebSocket, and that import has no constructor in
|
|
3519
3519
|
// workerd.
|
|
3520
3520
|
if (bridge.plane === 'cloud') {
|
|
3521
3521
|
const message =
|
|
3522
|
-
'
|
|
3522
|
+
'peach do reload is not available on a cloud simulator; it runs headless with no page to reload. restart the simulator instead.'
|
|
3523
3523
|
if (wantsJson(effectiveArgs)) {
|
|
3524
3524
|
printJson({ cleared: false, ready: false, error: message })
|
|
3525
3525
|
} else {
|
|
@@ -3744,7 +3744,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
3744
3744
|
if (!code) {
|
|
3745
3745
|
console.error(inspectUsage('js', '<javascript>'))
|
|
3746
3746
|
console.error('')
|
|
3747
|
-
console.error(' runs the snippet in the engine realm.
|
|
3747
|
+
console.error(' runs the snippet in the engine realm. peach is the')
|
|
3748
3748
|
console.error(' canonical state surface — reach into it directly.')
|
|
3749
3749
|
console.error('')
|
|
3750
3750
|
console.error(' examples:')
|
|
@@ -3794,24 +3794,24 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
3794
3794
|
const lc = code.toLowerCase()
|
|
3795
3795
|
const suggestions: string[] = []
|
|
3796
3796
|
if (lc.includes('sootsim:gohome') || lc.includes('gohome'))
|
|
3797
|
-
suggestions.push('
|
|
3797
|
+
suggestions.push('peach shell home')
|
|
3798
3798
|
if (lc.includes('sootsim:appswitcher') || lc.includes('appswitcher'))
|
|
3799
|
-
suggestions.push('
|
|
3799
|
+
suggestions.push('peach shell switcher')
|
|
3800
3800
|
if (lc.includes('keyboard.isvisible') || lc.includes('keyboard.getmode'))
|
|
3801
|
-
suggestions.push('
|
|
3802
|
-
if (lc.includes('interact.tap')) suggestions.push('
|
|
3803
|
-
if (lc.includes('keyboard.type')) suggestions.push('
|
|
3801
|
+
suggestions.push('peach debug state keyboard')
|
|
3802
|
+
if (lc.includes('interact.tap')) suggestions.push('peach do tap <x> <y>')
|
|
3803
|
+
if (lc.includes('keyboard.type')) suggestions.push('peach do type <text>')
|
|
3804
3804
|
if (lc.includes('keyboard.press') || lc.includes('keyboard.dispatchkey'))
|
|
3805
|
-
suggestions.push('
|
|
3806
|
-
if (lc.includes('keyboard.dismiss')) suggestions.push('
|
|
3807
|
-
if (lc.includes('dumptree')) suggestions.push('
|
|
3808
|
-
if (lc.includes('dumpaccessibilitytree')) suggestions.push('
|
|
3809
|
-
if (lc.includes('getnodecount')) suggestions.push('
|
|
3810
|
-
if (lc.includes('findbytext')) suggestions.push('
|
|
3805
|
+
suggestions.push('peach do key <name>')
|
|
3806
|
+
if (lc.includes('keyboard.dismiss')) suggestions.push('peach do dismiss')
|
|
3807
|
+
if (lc.includes('dumptree')) suggestions.push('peach get tree')
|
|
3808
|
+
if (lc.includes('dumpaccessibilitytree')) suggestions.push('peach get a11y')
|
|
3809
|
+
if (lc.includes('getnodecount')) suggestions.push('peach get count')
|
|
3810
|
+
if (lc.includes('findbytext')) suggestions.push('peach find <text>')
|
|
3811
3811
|
if (lc.includes('findbytestid') || lc.includes('findbyid'))
|
|
3812
|
-
suggestions.push('
|
|
3812
|
+
suggestions.push('peach find --testid <id>')
|
|
3813
3813
|
if (lc.includes('document.hidden'))
|
|
3814
|
-
suggestions.push('
|
|
3814
|
+
suggestions.push('peach debug state keyboard (includes tab health)')
|
|
3815
3815
|
if (suggestions.length > 0) {
|
|
3816
3816
|
maybeHint('prefer-cli-over-eval', suggestions)
|
|
3817
3817
|
}
|
|
@@ -3820,7 +3820,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
3820
3820
|
}
|
|
3821
3821
|
|
|
3822
3822
|
case 'globals': {
|
|
3823
|
-
// show all available
|
|
3823
|
+
// show all available peach globals and their methods
|
|
3824
3824
|
const info = await bridge.send({
|
|
3825
3825
|
type: 'evaluate',
|
|
3826
3826
|
code: `(async () => {
|
|
@@ -3862,7 +3862,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
3862
3862
|
return globals
|
|
3863
3863
|
})()`,
|
|
3864
3864
|
})
|
|
3865
|
-
console.log('
|
|
3865
|
+
console.log(' peach JS API:\n')
|
|
3866
3866
|
for (const [name, methods] of Object.entries(info as Record<string, string[]>)) {
|
|
3867
3867
|
console.log(` ${name}:`)
|
|
3868
3868
|
for (const m of methods) {
|
|
@@ -3882,7 +3882,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
3882
3882
|
|
|
3883
3883
|
case 'perf': {
|
|
3884
3884
|
if (invocationPrefix === 'debug' && !opts.internalPerfCommand) {
|
|
3885
|
-
console.error(' `
|
|
3885
|
+
console.error(' `peach debug perf` was removed. use `peach perf shell ...`.')
|
|
3886
3886
|
rnxExit(1)
|
|
3887
3887
|
}
|
|
3888
3888
|
const perfCmd = positional[1]
|
|
@@ -4316,20 +4316,20 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
4316
4316
|
}
|
|
4317
4317
|
|
|
4318
4318
|
case 'network': {
|
|
4319
|
-
//
|
|
4319
|
+
// peach network — live request inspector backed by the shared
|
|
4320
4320
|
// observability store (installed at engine boot, fed by worker-side
|
|
4321
4321
|
// fetch + XHR capture over BroadcastChannel).
|
|
4322
4322
|
//
|
|
4323
4323
|
// shapes:
|
|
4324
|
-
//
|
|
4325
|
-
//
|
|
4326
|
-
//
|
|
4327
|
-
//
|
|
4328
|
-
//
|
|
4329
|
-
//
|
|
4330
|
-
//
|
|
4331
|
-
//
|
|
4332
|
-
//
|
|
4324
|
+
// peach network [limit] last N entries (default 20)
|
|
4325
|
+
// peach network --failed only non-2xx / errored
|
|
4326
|
+
// peach network --slow only requests slower than --threshold (default 1000ms)
|
|
4327
|
+
// peach network --threshold <ms> customize slow threshold for --slow
|
|
4328
|
+
// peach network --filter <substring> url substring filter
|
|
4329
|
+
// peach network --json raw json output
|
|
4330
|
+
// peach network tail | -f follow mode (polls)
|
|
4331
|
+
// peach network get <id> detail for one entry
|
|
4332
|
+
// peach network clear drop the buffer
|
|
4333
4333
|
const sub = positional[1]
|
|
4334
4334
|
|
|
4335
4335
|
// manual flag scan — parseBridgeCliArgs already stripped these
|
|
@@ -4373,7 +4373,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
4373
4373
|
if (sub === 'get') {
|
|
4374
4374
|
const id = positional[2]
|
|
4375
4375
|
if (!id) {
|
|
4376
|
-
console.error(' usage:
|
|
4376
|
+
console.error(' usage: peach network get <id>')
|
|
4377
4377
|
rnxExit(1)
|
|
4378
4378
|
}
|
|
4379
4379
|
const entry = (await bridge.send({
|
|
@@ -4509,17 +4509,17 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
4509
4509
|
}
|
|
4510
4510
|
|
|
4511
4511
|
case 'logs': {
|
|
4512
|
-
//
|
|
4512
|
+
// peach logs — live console inspector backed by the shared
|
|
4513
4513
|
// observability log store (fed by worker-side console capture over
|
|
4514
|
-
// BroadcastChannel). mirrors `
|
|
4514
|
+
// BroadcastChannel). mirrors `peach network`:
|
|
4515
4515
|
//
|
|
4516
|
-
//
|
|
4517
|
-
//
|
|
4518
|
-
//
|
|
4519
|
-
//
|
|
4520
|
-
//
|
|
4521
|
-
//
|
|
4522
|
-
//
|
|
4516
|
+
// peach logs [limit] last N entries (default 50)
|
|
4517
|
+
// peach logs --level error,warn filter by level (csv)
|
|
4518
|
+
// peach logs --filter <str> message substring filter
|
|
4519
|
+
// peach logs --internal include engine-internal [sootsim] logs (hidden by default)
|
|
4520
|
+
// peach logs --json raw json output
|
|
4521
|
+
// peach logs tail | -f follow mode (polls)
|
|
4522
|
+
// peach logs clear drop the buffer
|
|
4523
4523
|
const sub = positional[1]
|
|
4524
4524
|
|
|
4525
4525
|
let filter: string | null = null
|
|
@@ -4638,11 +4638,11 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
4638
4638
|
// auto-settle after any write command so the next CLI call doesn't see
|
|
4639
4639
|
// mid-transition state. short deadline — if the app has a perpetual
|
|
4640
4640
|
// background animation, we bail to layout-only stability via the same
|
|
4641
|
-
// logic `do settle` uses. opt-out: --no-wait or
|
|
4641
|
+
// logic `do settle` uses. opt-out: --no-wait or PEACH_NO_AUTO_WAIT=1.
|
|
4642
4642
|
if (
|
|
4643
4643
|
writeCommands.has(subcommand) &&
|
|
4644
4644
|
!args.includes('--no-wait') &&
|
|
4645
|
-
process.env.
|
|
4645
|
+
process.env.PEACH_NO_AUTO_WAIT !== '1' &&
|
|
4646
4646
|
!(await shouldSkipAutoSettleForInspectPick(bridge, subcommand))
|
|
4647
4647
|
) {
|
|
4648
4648
|
await autoSettleAfterWrite(bridge)
|
|
@@ -4677,7 +4677,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
4677
4677
|
} catch (err: any) {
|
|
4678
4678
|
rethrowIfExit(err)
|
|
4679
4679
|
const message = err instanceof Error ? err.message : String(err)
|
|
4680
|
-
console.error(` ${subcommand ?? '
|
|
4680
|
+
console.error(` ${subcommand ?? 'peach'} failed: ${message}`)
|
|
4681
4681
|
const unknownSim = /^no sim connected with id ([^;]+)(?:; connected sims: .+)?$/.exec(
|
|
4682
4682
|
message,
|
|
4683
4683
|
)
|
|
@@ -4710,9 +4710,9 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
4710
4710
|
process.stderr.write(
|
|
4711
4711
|
` the sim is still responsive — '${cmd}' just exceeded the ${timedOut[1]}s command budget.\n` +
|
|
4712
4712
|
` the screen's node tree is large; narrow the query or raise the budget:\n` +
|
|
4713
|
-
`
|
|
4714
|
-
`
|
|
4715
|
-
`
|
|
4713
|
+
` peach --testid <id> # scope to one subtree\n` +
|
|
4714
|
+
` peach find --testid <id> # targeted single-node lookup\n` +
|
|
4715
|
+
` peach --timeout 60000 # raise per-command budget (ms)\n`,
|
|
4716
4716
|
)
|
|
4717
4717
|
} else {
|
|
4718
4718
|
printRecoverHint()
|