react-native-ai-devtools 1.4.19 → 1.4.21
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/README.md +109 -107
- package/build/core/executor.d.ts +36 -1
- package/build/core/executor.d.ts.map +1 -1
- package/build/core/executor.js +193 -46
- package/build/core/executor.js.map +1 -1
- package/build/core/index.d.ts +1 -1
- package/build/core/index.d.ts.map +1 -1
- package/build/core/index.js +1 -1
- package/build/core/index.js.map +1 -1
- package/build/index.js +54 -14
- package/build/index.js.map +1 -1
- package/package.json +1 -1
package/build/index.js
CHANGED
|
@@ -27,7 +27,7 @@ connectMetroBuildEvents, disconnectMetroBuildEvents, getBundleErrors, getBundleS
|
|
|
27
27
|
// Error screen parsing (OCR fallback)
|
|
28
28
|
parseErrorScreenText, formatParsedError,
|
|
29
29
|
// OCR
|
|
30
|
-
recognizeText, inferIOSDevicePixelRatio,
|
|
30
|
+
recognizeText, inferIOSDevicePixelRatio, enrichScreenshotWithLayout,
|
|
31
31
|
// Android
|
|
32
32
|
listAndroidDevices, androidScreenshot, androidInstallApp, androidLaunchApp, androidListPackages,
|
|
33
33
|
// Android UI Input (Phase 2)
|
|
@@ -1470,7 +1470,7 @@ registerToolWithTelemetry("tap", {
|
|
|
1470
1470
|
"- tap(text=\"Submit\") — finds and taps element with matching text\n" +
|
|
1471
1471
|
"- tap(testID=\"login-btn\") — finds by testID\n" +
|
|
1472
1472
|
"- tap(component=\"HamburgerIcon\") — finds by React component name\n" +
|
|
1473
|
-
"- tap(x=300, y=600) — taps at pixel coordinates
|
|
1473
|
+
"- tap(x=300, y=600) — taps at pixel coordinates (LAST RESORT — only use if text/testID/component strategies all fail)\n" +
|
|
1474
1474
|
"- tap(text=\"Menu\", strategy=\"ocr\") — forces OCR strategy only\n" +
|
|
1475
1475
|
"- tap(x=300, y=600, native=true, platform=\"android\") — taps directly via ADB/simctl without React Native connection\n\n" +
|
|
1476
1476
|
"Returns a post-tap screenshot by default (set screenshot=false to disable). " +
|
|
@@ -2648,7 +2648,7 @@ registerToolWithTelemetry("list_android_devices", {
|
|
|
2648
2648
|
});
|
|
2649
2649
|
// Tool: Android screenshot
|
|
2650
2650
|
registerToolWithTelemetry("android_screenshot", {
|
|
2651
|
-
description: "Take a screenshot from an Android device/emulator. Returns the image
|
|
2651
|
+
description: "Take a screenshot from an Android device/emulator. Returns the image and a screen layout overlay showing visible React components with names, text content, hierarchy, and tap-ready pixel coordinates. Use component names for inspect_component/find_components. Use tap(text=...) for interaction — only fall back to tap(x,y) coordinates from the layout if all tap strategies fail.",
|
|
2652
2652
|
inputSchema: {
|
|
2653
2653
|
outputPath: z
|
|
2654
2654
|
.string()
|
|
@@ -2705,6 +2705,16 @@ registerToolWithTelemetry("android_screenshot", {
|
|
|
2705
2705
|
catch {
|
|
2706
2706
|
// Use defaults
|
|
2707
2707
|
}
|
|
2708
|
+
// Enrich with screen layout data (component names + tap coordinates)
|
|
2709
|
+
// Android: density ratio = densityDpi / 160 (160dpi = 1dp = 1px baseline)
|
|
2710
|
+
const androidPixelRatio = densityDpi / 160;
|
|
2711
|
+
let layoutText = null;
|
|
2712
|
+
try {
|
|
2713
|
+
layoutText = await enrichScreenshotWithLayout(androidPixelRatio, result.scaleFactor || 1);
|
|
2714
|
+
}
|
|
2715
|
+
catch {
|
|
2716
|
+
// Non-fatal: screenshot works without layout enrichment
|
|
2717
|
+
}
|
|
2708
2718
|
infoText += `\n📱 Android uses PIXELS for all coordinates`;
|
|
2709
2719
|
if (result.scaleFactor && result.scaleFactor > 1) {
|
|
2710
2720
|
infoText += `\n🖼️ Image was scaled down to fit API limits (scale: ${result.scaleFactor.toFixed(3)})`;
|
|
@@ -2715,11 +2725,22 @@ registerToolWithTelemetry("android_screenshot", {
|
|
|
2715
2725
|
}
|
|
2716
2726
|
infoText += `\n⚠️ Status bar: ${statusBarPixels}px (${statusBarDp}dp) from top - app content starts below this`;
|
|
2717
2727
|
infoText += `\n📊 Display density: ${densityDpi}dpi`;
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2728
|
+
if (layoutText) {
|
|
2729
|
+
infoText += `\n\n📋 Screen Layout (components with tap coordinates in pixels):`;
|
|
2730
|
+
infoText += `\n${layoutText}`;
|
|
2731
|
+
infoText += `\n\n💡 Next steps:`;
|
|
2732
|
+
infoText += `\n • tap(text="Button Label") — tap element by visible text (preferred)`;
|
|
2733
|
+
infoText += `\n • tap(testID="id") or tap(component="Name") — tap by testID or component name`;
|
|
2734
|
+
infoText += `\n • tap(x=<px>, y=<px>) — use tap coordinates from layout above ONLY if text/testID/component tap fails`;
|
|
2735
|
+
infoText += `\n • inspect_component("ComponentName") — inspect a component from the layout above`;
|
|
2736
|
+
}
|
|
2737
|
+
else {
|
|
2738
|
+
infoText += `\n\n💡 Next steps:`;
|
|
2739
|
+
infoText += `\n • tap(text="Button Label") — tap element by visible text`;
|
|
2740
|
+
infoText += `\n • tap(x=<px>, y=<px>) — tap at coordinates from this screenshot`;
|
|
2741
|
+
infoText += `\n • android_describe_all — get full UI tree with exact tap coordinates`;
|
|
2742
|
+
infoText += `\n • android_find_element(text="...") — find element coordinates without tapping`;
|
|
2743
|
+
}
|
|
2723
2744
|
// Check for LogBox overlay (uses default CDP device — native deviceId cannot be mapped to CDP device name)
|
|
2724
2745
|
try {
|
|
2725
2746
|
const logBoxState = await detectLogBox();
|
|
@@ -3189,7 +3210,7 @@ registerToolWithTelemetry("list_ios_simulators", {
|
|
|
3189
3210
|
});
|
|
3190
3211
|
// Tool: iOS screenshot
|
|
3191
3212
|
registerToolWithTelemetry("ios_screenshot", {
|
|
3192
|
-
description: "Take a screenshot from an iOS simulator. Returns the image
|
|
3213
|
+
description: "Take a screenshot from an iOS simulator. Returns the image and a screen layout overlay showing visible React components with names, text content, hierarchy, and tap-ready pixel coordinates. Use component names for inspect_component/find_components. Use tap(text=...) for interaction — only fall back to tap(x,y) coordinates from the layout if all tap strategies fail.",
|
|
3193
3214
|
inputSchema: {
|
|
3194
3215
|
outputPath: z
|
|
3195
3216
|
.string()
|
|
@@ -3273,6 +3294,14 @@ registerToolWithTelemetry("ios_screenshot", {
|
|
|
3273
3294
|
pointHeight = Math.round(pixelHeight / scaleFactor);
|
|
3274
3295
|
}
|
|
3275
3296
|
const safeAreaOffsetPixels = safeAreaTop * scaleFactor;
|
|
3297
|
+
// Enrich with screen layout data (component names + tap coordinates)
|
|
3298
|
+
let layoutText = null;
|
|
3299
|
+
try {
|
|
3300
|
+
layoutText = await enrichScreenshotWithLayout(scaleFactor, result.scaleFactor || 1);
|
|
3301
|
+
}
|
|
3302
|
+
catch {
|
|
3303
|
+
// Non-fatal: screenshot works without layout enrichment
|
|
3304
|
+
}
|
|
3276
3305
|
let infoText = `Screenshot captured (${pixelWidth}x${pixelHeight} pixels)`;
|
|
3277
3306
|
infoText += `\n📱 iOS screen: ${pointWidth}x${pointHeight} points (${scaleFactor}x scale)`;
|
|
3278
3307
|
infoText += `\n📐 tap() handles pixel-to-point conversion automatically — pass pixel coords from this image directly`;
|
|
@@ -3280,11 +3309,22 @@ registerToolWithTelemetry("ios_screenshot", {
|
|
|
3280
3309
|
if (result.scaleFactor && result.scaleFactor > 1) {
|
|
3281
3310
|
infoText += `\n🖼️ Image was scaled down to fit API limits (scale: ${result.scaleFactor.toFixed(3)})`;
|
|
3282
3311
|
}
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3312
|
+
if (layoutText) {
|
|
3313
|
+
infoText += `\n\n📋 Screen Layout (components with tap coordinates in pixels):`;
|
|
3314
|
+
infoText += `\n${layoutText}`;
|
|
3315
|
+
infoText += `\n\n💡 Next steps:`;
|
|
3316
|
+
infoText += `\n • tap(text="Button Label") — tap element by visible text (preferred)`;
|
|
3317
|
+
infoText += `\n • tap(testID="id") or tap(component="Name") — tap by testID or component name`;
|
|
3318
|
+
infoText += `\n • tap(x=<px>, y=<px>) — use tap coordinates from layout above ONLY if text/testID/component tap fails`;
|
|
3319
|
+
infoText += `\n • inspect_component("ComponentName") — inspect a component from the layout above`;
|
|
3320
|
+
}
|
|
3321
|
+
else {
|
|
3322
|
+
infoText += `\n\n💡 Next steps:`;
|
|
3323
|
+
infoText += `\n • tap(text="Button Label") — tap element by visible text`;
|
|
3324
|
+
infoText += `\n • tap(x=<px>, y=<px>) — tap at coordinates from this screenshot`;
|
|
3325
|
+
infoText += `\n • ios_describe_all — get full UI tree with exact tap coordinates`;
|
|
3326
|
+
infoText += `\n • ios_find_element(label="...") — find element coordinates without tapping`;
|
|
3327
|
+
}
|
|
3288
3328
|
// Check for LogBox overlay (uses default CDP device — native UDID cannot be mapped to CDP device name)
|
|
3289
3329
|
try {
|
|
3290
3330
|
const logBoxState = await detectLogBox();
|