execbro 2.9.6 → 2.9.7
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/build/core/guides.d.ts.map +1 -1
- package/build/core/guides.js +82 -13
- package/build/core/guides.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guides.d.ts","sourceRoot":"","sources":["../../src/core/guides.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,KAAK;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACnB;
|
|
1
|
+
{"version":3,"file":"guides.d.ts","sourceRoot":"","sources":["../../src/core/guides.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,KAAK;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACnB;AAujBD,eAAO,MAAM,aAAa,EAAE,MAchB,CAAC;AAEb,wBAAgB,gBAAgB,IAAI,MAAM,CAWzC;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI5D;AAED,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAE7C"}
|
package/build/core/guides.js
CHANGED
|
@@ -21,8 +21,18 @@ const guides = [
|
|
|
21
21
|
- list_devices — iOS simulators, Android emulators, and physical devices in one call
|
|
22
22
|
- ios_boot_simulator — boot an iOS simulator if needed
|
|
23
23
|
- ios_launch_app / android_launch_app — launch the app
|
|
24
|
+
- ios_terminate_app — kill an app that is in a bad state before relaunching
|
|
25
|
+
- android_list_packages — find the package name when you only know the app by sight
|
|
24
26
|
- Wait 2-3 seconds, then scan_metro
|
|
25
27
|
|
|
28
|
+
## Stale Bundle After a Metro Restart
|
|
29
|
+
scan_metro detects that the process serving a port CHANGED (pid via lsof) and says so. It means
|
|
30
|
+
Fast Refresh history is discontinuous: edits made while Metro was down are NOT in the running
|
|
31
|
+
bundle, and reconnecting does not reconcile them. Devices attached on a restarted port are
|
|
32
|
+
flagged, and tap, swipe and get_screen_state carry a staleBundle warning until reload_app clears
|
|
33
|
+
it. Believe the warning — every other signal reads healthy, so stale behaviour otherwise looks
|
|
34
|
+
exactly like "my fix didn't work".
|
|
35
|
+
|
|
26
36
|
## Switch to Native Debugger
|
|
27
37
|
- disconnect_metro — closes all CDP connections and stops auto-reconnect
|
|
28
38
|
- The built-in React Native debugger can now connect
|
|
@@ -33,7 +43,8 @@ const guides = [
|
|
|
33
43
|
- connect_metro: connect to specific port (when you know it)
|
|
34
44
|
- disconnect_metro: close all connections (free CDP slot for native debugger)
|
|
35
45
|
- ensure_connection: health check with healthCheck=true
|
|
36
|
-
- get_connection_status: check uptime and gaps
|
|
46
|
+
- get_connection_status: check uptime and gaps
|
|
47
|
+
- get_license_status: installation id and license tier (activate_license / delete_account manage it)`
|
|
37
48
|
},
|
|
38
49
|
{
|
|
39
50
|
id: "inspect",
|
|
@@ -42,9 +53,9 @@ const guides = [
|
|
|
42
53
|
content: `# Component Inspection
|
|
43
54
|
|
|
44
55
|
## Recommended Workflow: Identify a Component on Screen
|
|
45
|
-
1.
|
|
46
|
-
2.
|
|
47
|
-
3. Pass
|
|
56
|
+
1. get_screen_state — screenshot-free, and every element comes back with a ready (x, y). Start here; only fall back to a screenshot (ios_screenshot / android_screenshot / ocr_screenshot) when you need to see the element to pick it out
|
|
57
|
+
2. Take the coordinate from that listing, or estimate it off the screenshot
|
|
58
|
+
3. Pass it straight through — every layout tool, tap() and the screenshots share one screen-space coordinate system, so no conversion is needed
|
|
48
59
|
4. Pick the right tool (see decision below) and call it with (x, y)
|
|
49
60
|
|
|
50
61
|
### inspect_at_point(x, y)
|
|
@@ -53,7 +64,7 @@ NO overlay, zero visual side effect, safe to call rapidly or across a transition
|
|
|
53
64
|
|
|
54
65
|
Returns:
|
|
55
66
|
- element name and full owner-tree path
|
|
56
|
-
- FRAME PER ANCESTOR (position/size
|
|
67
|
+
- FRAME PER ANCESTOR (position/size for every ancestor that hit-tested the point, in delivered-screenshot pixels — the same space as screenshots and tap)
|
|
57
68
|
- PROPS of the innermost component (handlers as [Function], refs, testID, custom props)
|
|
58
69
|
- the node's own style object
|
|
59
70
|
- source {file, line, column} plus the owner chain as "Source ancestors" (set source=false to skip in tight loops)
|
|
@@ -72,6 +83,7 @@ looks wrong and isn't on the node itself, walk the ancestors it returns.
|
|
|
72
83
|
- find_components(pattern) — regex search by component name across the fiber tree.
|
|
73
84
|
- get_component_tree — compact names-only structure by default; pass structureOnly=false only when you genuinely need props/styles for the whole tree.
|
|
74
85
|
- inspect_component(name) — deep dive into a specific component's props, state, and hooks.
|
|
86
|
+
- measure(componentName) — the reverse of inspect_at_point: geometry {x, y, width, height} for a component you can name, without hand-rolling a fiber walk in execute_in_app.
|
|
75
87
|
|
|
76
88
|
## Tips
|
|
77
89
|
- Works on Paper, Fabric, and Bridgeless / new arch.
|
|
@@ -125,16 +137,22 @@ size in a note when it applies.
|
|
|
125
137
|
- Style is the node's own style object, not a merged cascade — walk the returned ancestors when a value isn't on the node itself.
|
|
126
138
|
|
|
127
139
|
## Full Screen Layout
|
|
128
|
-
- get_screen_layout — full layout data for all components
|
|
129
|
-
|
|
140
|
+
- get_screen_layout — full layout data for all components. Host components (View, Text) are
|
|
141
|
+
already filtered out; the tree is custom components only, so there is nothing to switch off
|
|
142
|
+
- Use extended=true for layout styles (padding, margin, flex, backgroundColor)
|
|
130
143
|
- find_components with includeLayout=true for targeted layout info
|
|
144
|
+
- measure(componentName) — geometry for one named component, when you know the name and only
|
|
145
|
+
want its frame
|
|
131
146
|
|
|
132
147
|
## Key Tools
|
|
133
148
|
- get_screen_state: route + overlays + every element, screenshot-free (start here)
|
|
134
149
|
- ios_screenshot / android_screenshot: visual capture
|
|
135
150
|
- tap: also returns a post-tap screenshot by default (no separate screenshot call needed after tapping)
|
|
136
151
|
- ocr_screenshot: screenshot with text recognition and tap coordinates
|
|
137
|
-
- inspect_at_point: frames per ancestor + props + source file:line (no overlay, fast)
|
|
152
|
+
- inspect_at_point: frames per ancestor + props + source file:line (no overlay, fast)
|
|
153
|
+
- measure: geometry for one named component
|
|
154
|
+
- get_images: re-read any screenshot already captured (including tap burst frames) instead of taking another
|
|
155
|
+
- logbox: dismiss / ignore / push / detect the LogBox overlay — dismiss returns the full error content, so nothing is lost by clearing it`
|
|
138
156
|
},
|
|
139
157
|
{
|
|
140
158
|
id: "interact",
|
|
@@ -159,6 +177,13 @@ Use tap — it tries multiple strategies automatically and returns a post-tap sc
|
|
|
159
177
|
tap returns a screenshot after every action (screenshot=true by default) — no need to call ios_screenshot/android_screenshot after tapping.
|
|
160
178
|
For coordinate/accessibility/OCR taps, it also verifies if the tap caused a visual change (verify=true by default). Set screenshot=false for fastest execution.
|
|
161
179
|
|
|
180
|
+
### When verification says meaningful:false but you think the tap landed
|
|
181
|
+
Retry with burst=true. It captures 4 rapid screenshots after the tap, catching press animations
|
|
182
|
+
and highlights that settle before the ordinary after-screenshot. Then read
|
|
183
|
+
verification.transientChangeDetected, and pull the individual frames with
|
|
184
|
+
get_images({groupId: verification.burstGroupId}) — the frames are already in the shared image
|
|
185
|
+
buffer, so inspecting them costs no extra capture.
|
|
186
|
+
|
|
162
187
|
## Long Press
|
|
163
188
|
Pass duration (milliseconds) to hold the touch instead of releasing it: tap(testID="row-3", duration=800). Use it for context menus, drag starts and multi-select. React Native fires onLongPress at 500ms, so anything under 500 will not trigger it; 800 is a safe default. Works on both platforms and with every targeting strategy (testID, text, component, coordinates).
|
|
164
189
|
|
|
@@ -243,6 +268,17 @@ tap(text=...) skips fiber for non-ASCII (Hermes limitation) and uses accessibili
|
|
|
243
268
|
- dismiss_keyboard: blur the focused input, closing the keyboard.
|
|
244
269
|
- ios_button / android_key_event: hardware buttons (HOME, BACK, etc.)
|
|
245
270
|
- ios_open_url: deep links and universal links
|
|
271
|
+
- get_images: retrieve screenshots already captured by any tool, including tap burst frames
|
|
272
|
+
|
|
273
|
+
## Jumping Straight to a Screen
|
|
274
|
+
navigate drives the app's router instead of tapping through the UI, and checks the route
|
|
275
|
+
actually moved: navigate({to:"/settings"}) -> read changed -> get_screen_state.
|
|
276
|
+
Destinations are NOT interchangeable — Expo Router takes paths ("/event-details?id=1"),
|
|
277
|
+
React Navigation takes route names ("TarotNav"); the response says which router resolved, and
|
|
278
|
+
unknown React Navigation names are rejected before dispatch with nearest-match suggestions.
|
|
279
|
+
navigate({action:"back"}) and {action:"reset"} are available too. changed=false means it settled
|
|
280
|
+
without moving; indeterminate=true means no settled reading. Prefer this over a hand-written
|
|
281
|
+
router call through execute_in_app, which reports success whenever nothing throws.
|
|
246
282
|
|
|
247
283
|
## After Interactions
|
|
248
284
|
- Take a screenshot to verify the result`
|
|
@@ -262,10 +298,18 @@ tap(text=...) skips fiber for non-ASCII (Hermes limitation) and uses accessibili
|
|
|
262
298
|
3. clear_logs — reset buffer, then re-capture after a specific action
|
|
263
299
|
|
|
264
300
|
## Key Tools
|
|
265
|
-
- get_logs: retrieve logs with filtering (level, maxLogs, summary, verbose, startFromText)
|
|
301
|
+
- get_logs: retrieve logs with filtering (level, maxLogs, summary, verbose, startFromText, epoch)
|
|
266
302
|
- search_logs: text search across all captured logs
|
|
267
303
|
- clear_logs: reset the log buffer
|
|
268
304
|
|
|
305
|
+
## App Restarts (epochs)
|
|
306
|
+
Every log and network entry carries a per-device epoch that increments on each new app run, and
|
|
307
|
+
the output draws a "── app restarted (epoch N) ──" divider at each boundary. The default is
|
|
308
|
+
epoch="all", so pre-restart data is never hidden from you — pass epoch="current" to read only the
|
|
309
|
+
run in front of you, or a number for one specific run. get_network_requests takes the same
|
|
310
|
+
parameter. When a crash and its aftermath sit in one read, the divider is what tells you which
|
|
311
|
+
side of the restart a message came from.
|
|
312
|
+
|
|
269
313
|
## NATIVE LOGS (crashes the JS console cannot see)
|
|
270
314
|
|
|
271
315
|
get_logs(source="native") reads Android logcat / iOS os_log, filtered to your
|
|
@@ -356,6 +400,12 @@ are trying to fix.
|
|
|
356
400
|
network_replay({requestId}) re-issues a captured request, optionally with a
|
|
357
401
|
changed body or header, without driving the UI back to the screen that made it.
|
|
358
402
|
|
|
403
|
+
app_request issues a NEW request from inside the app, as the logged-in user — through the app's
|
|
404
|
+
real network stack, TLS trust and proxy config. Use it to reproduce a 4xx, check what an endpoint
|
|
405
|
+
returns for an edge case, or clean up test records the UI cannot reach. auth="auto" resolves the
|
|
406
|
+
token in-app, so the credential never enters the transcript; a hand-written fetch in
|
|
407
|
+
execute_in_app either digs the token out of redux or embeds a JWT literal, which does.
|
|
408
|
+
|
|
359
409
|
## Key Tools
|
|
360
410
|
- get_network_requests: list requests with filters (urlPattern, method, status, summary)
|
|
361
411
|
- search_network: search by URL pattern
|
|
@@ -364,6 +414,7 @@ changed body or header, without driving the UI back to the screen that made it.
|
|
|
364
414
|
- network_mock: replace or tamper with responses (add / list / remove / clear)
|
|
365
415
|
- network_condition: offline / slow / normal
|
|
366
416
|
- network_replay: re-issue a captured request, with optional overrides
|
|
417
|
+
- app_request: issue a new request from inside the app, authenticated, without putting the token in the transcript
|
|
367
418
|
|
|
368
419
|
## Tips
|
|
369
420
|
- Start with summary=true to see the request landscape
|
|
@@ -402,9 +453,12 @@ If the app called \`init({ stores, navigation, custom })\`, prefer the SDK paths
|
|
|
402
453
|
## Common Patterns (no SDK)
|
|
403
454
|
- Read Redux: execute_in_app("globalThis.__REDUX_STORE__.getState().sliceName")
|
|
404
455
|
- Dispatch action: execute_in_app("globalThis.__dispatch__(globalThis.__REDUX_ACTIONS__.slice.action(args))")
|
|
405
|
-
- Navigate: execute_in_app("globalThis.__navigate__('ScreenName')")
|
|
406
456
|
- Current route: execute_in_app("globalThis.__getCurrentRoute__()")
|
|
407
457
|
|
|
458
|
+
Note: do NOT navigate this way. A router call through execute_in_app reports success whenever
|
|
459
|
+
nothing throws — a path sent to a React Navigation ref changes nothing and warns only in LogBox.
|
|
460
|
+
Use the navigate tool, which verifies the route actually moved (see the "interact" guide).
|
|
461
|
+
|
|
408
462
|
## Long-Running Expressions
|
|
409
463
|
- Pass timeoutMs to raise the 10s default (capped at 120000) — the promise poll ladder is derived from it, so a big budget is actually used
|
|
410
464
|
- A promise that outlives the budget is kept in the app and its handle returned: execute_in_app({collect:"<handle>", waitMs:30000}) blocks server-side until it settles instead of making you poll
|
|
@@ -433,20 +487,35 @@ If the app called \`init({ stores, navigation, custom })\`, prefer the SDK paths
|
|
|
433
487
|
4. get_bundle_errors({ clear: true }) — read, then reset the error buffer
|
|
434
488
|
5. reload_app — trigger full JS bundle reload (only if needed)
|
|
435
489
|
|
|
490
|
+
## Did My Edit Land? (ask before reloading)
|
|
491
|
+
get_refresh_status answers whether the JS runtime ACCEPTED a Fast Refresh update, which is a
|
|
492
|
+
different question from whether Metro compiled (get_bundle_status). Capture a Date.now() BEFORE
|
|
493
|
+
editing, wait ~2s after saving, then get_refresh_status({since: <that timestamp>}) — updateCount
|
|
494
|
+
> 0 means the edit is in the running app. Use it instead of reloading on a hunch, and instead of
|
|
495
|
+
polling logs or screenshots. A full reload resets its ring buffer, so the next call reports
|
|
496
|
+
"recorder just installed".
|
|
497
|
+
|
|
436
498
|
## When to Reload
|
|
437
499
|
React Native has Fast Refresh by default. Only reload_app when:
|
|
438
|
-
-
|
|
500
|
+
- get_refresh_status shows no update accepted after a few seconds
|
|
439
501
|
- App is in a broken/error state
|
|
440
502
|
- Need to reset full app state (navigation, context)
|
|
441
503
|
- Made changes to native code or config files
|
|
442
504
|
|
|
505
|
+
reload_app reconnects itself — do NOT follow it with scan_metro. The fresh runtime often answers
|
|
506
|
+
no CDP probe within the tool's own wait, so the reply says reconnect is still in progress and a
|
|
507
|
+
backoff loop finishes it a few seconds later; get_apps immediately after such a reply can
|
|
508
|
+
legitimately come back empty. A reflexive scan_metro there throws away the navigation stack, auth
|
|
509
|
+
and in-memory caches for nothing.
|
|
510
|
+
|
|
443
511
|
## Red Screen Errors
|
|
444
512
|
If no errors captured via CDP, use get_bundle_errors with platform="ios" or "android" — this triggers screenshot+OCR fallback to read errors from the device screen.
|
|
445
513
|
|
|
446
514
|
## Key Tools
|
|
447
|
-
- get_bundle_status: Metro health check
|
|
515
|
+
- get_bundle_status: Metro health check (did it compile?)
|
|
516
|
+
- get_refresh_status: did the running runtime accept the Fast Refresh update?
|
|
448
517
|
- get_bundle_errors: compilation errors
|
|
449
|
-
- reload_app: full JS bundle reload
|
|
518
|
+
- reload_app: full JS bundle reload — reconnects itself, no scan_metro afterwards
|
|
450
519
|
- ensure_connection: verify connection with healthCheck=true`
|
|
451
520
|
},
|
|
452
521
|
{
|
package/build/core/guides.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guides.js","sourceRoot":"","sources":["../../src/core/guides.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,GAAY;IACpB;QACI,EAAE,EAAE,OAAO;QACX,KAAK,EAAE,eAAe;QACtB,OAAO,EAAE,yDAAyD;QAClE,OAAO,EAAE
|
|
1
|
+
{"version":3,"file":"guides.js","sourceRoot":"","sources":["../../src/core/guides.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "execbro",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.7",
|
|
4
4
|
"mcpName": "com.execbro/execbro",
|
|
5
5
|
"description": "ExecBro: React Native AI debugger and devtools MCP server. Gives AI agents eyes and hands in your running app (logs, network, state inspection, tap, screenshot).",
|
|
6
6
|
"type": "module",
|