react-native-ai-devtools 1.4.31 → 1.4.33
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 +81 -74
- package/build/core/executor.d.ts +1 -0
- package/build/core/executor.d.ts.map +1 -1
- package/build/core/executor.js +117 -31
- package/build/core/executor.js.map +1 -1
- package/build/index.js +65 -13
- package/build/index.js.map +1 -1
- package/package.json +1 -1
package/build/index.js
CHANGED
|
@@ -1603,7 +1603,7 @@ registerToolWithTelemetry("tap", {
|
|
|
1603
1603
|
"- tap(text=\"Submit\") — finds and taps element with matching text\n" +
|
|
1604
1604
|
"- tap(testID=\"login-btn\") — finds by testID\n" +
|
|
1605
1605
|
"- tap(component=\"HamburgerIcon\") — finds by React component name\n" +
|
|
1606
|
-
"- tap(x=300, y=600) — taps at pixel coordinates
|
|
1606
|
+
"- tap(x=300, y=600) — taps at pixel coordinates; use coordinates from the pressable elements list returned by ios_screenshot/android_screenshot for reliable icon and ambiguous-element taps\n" +
|
|
1607
1607
|
"- tap(text=\"Menu\", strategy=\"ocr\") — forces OCR strategy only\n" +
|
|
1608
1608
|
"- tap(x=300, y=600, native=true, platform=\"android\") — taps directly via ADB/simctl without React Native connection\n\n" +
|
|
1609
1609
|
"Returns a post-tap screenshot by default (set screenshot=false to disable). " +
|
|
@@ -2781,7 +2781,7 @@ registerToolWithTelemetry("list_android_devices", {
|
|
|
2781
2781
|
});
|
|
2782
2782
|
// Tool: Android screenshot
|
|
2783
2783
|
registerToolWithTelemetry("android_screenshot", {
|
|
2784
|
-
description: "Take a screenshot from an Android device/emulator. Returns the image
|
|
2784
|
+
description: "Take a screenshot from an Android device/emulator. Returns the image plus two lists: (1) pressable elements — the tappable components on screen with ready-to-use pixel tap coordinates, testIDs, and labels; (2) screen layout — all visible React components for context. Prefer tap(text=\"...\") when text is exact and unique; otherwise use tap(x, y) with coordinates from the pressables list — this is the most reliable way to tap icons or visually-identified elements. Use component names from the layout for inspect_component/find_components.",
|
|
2785
2785
|
inputSchema: {
|
|
2786
2786
|
outputPath: z
|
|
2787
2787
|
.string()
|
|
@@ -2848,6 +2848,26 @@ registerToolWithTelemetry("android_screenshot", {
|
|
|
2848
2848
|
catch {
|
|
2849
2849
|
// Non-fatal: screenshot works without layout enrichment
|
|
2850
2850
|
}
|
|
2851
|
+
// Enrich with pressable elements (filtered list of tappable components, converted to screenshot pixel coords)
|
|
2852
|
+
let pressablesText = null;
|
|
2853
|
+
try {
|
|
2854
|
+
const pressables = await getPressableElements({});
|
|
2855
|
+
if (pressables.success && pressables.parsedElements && pressables.parsedElements.length > 0) {
|
|
2856
|
+
const screenshotScale = result.scaleFactor || 1;
|
|
2857
|
+
pressablesText = pressables.parsedElements.map((el) => {
|
|
2858
|
+
const px = Math.round((el.center.x * androidPixelRatio) / screenshotScale);
|
|
2859
|
+
const py = Math.round((el.center.y * androidPixelRatio) / screenshotScale);
|
|
2860
|
+
const label = el.accessibilityLabel || el.text || el.testID || el.component;
|
|
2861
|
+
const idPart = el.testID ? ` testID="${el.testID}"` : "";
|
|
2862
|
+
const kindPart = el.isInput ? " [input]" : "";
|
|
2863
|
+
const wrapPart = el.isWrapper ? " [wrapper — skip]" : "";
|
|
2864
|
+
return ` (${px}, ${py}) ${el.component}: "${label}"${idPart}${kindPart}${wrapPart}`;
|
|
2865
|
+
}).join("\n");
|
|
2866
|
+
}
|
|
2867
|
+
}
|
|
2868
|
+
catch {
|
|
2869
|
+
// Non-fatal: screenshot works without pressables enrichment
|
|
2870
|
+
}
|
|
2851
2871
|
infoText += `\n📱 Android uses PIXELS for all coordinates`;
|
|
2852
2872
|
if (result.scaleFactor && result.scaleFactor > 1) {
|
|
2853
2873
|
infoText += `\n🖼️ Image was scaled down to fit API limits (scale: ${result.scaleFactor.toFixed(3)})`;
|
|
@@ -2858,14 +2878,20 @@ registerToolWithTelemetry("android_screenshot", {
|
|
|
2858
2878
|
}
|
|
2859
2879
|
infoText += `\n⚠️ Status bar: ${statusBarPixels}px (${statusBarDp}dp) from top - app content starts below this`;
|
|
2860
2880
|
infoText += `\n📊 Display density: ${densityDpi}dpi`;
|
|
2881
|
+
if (pressablesText) {
|
|
2882
|
+
infoText += `\n\n🎯 Pressable elements (ready-to-tap, coordinates in screenshot pixels):`;
|
|
2883
|
+
infoText += `\n${pressablesText}`;
|
|
2884
|
+
}
|
|
2861
2885
|
if (layoutText) {
|
|
2862
|
-
infoText += `\n\n📋 Screen Layout (components
|
|
2886
|
+
infoText += `\n\n📋 Screen Layout (all components, tap coordinates in pixels):`;
|
|
2863
2887
|
infoText += `\n${layoutText}`;
|
|
2888
|
+
}
|
|
2889
|
+
if (pressablesText || layoutText) {
|
|
2864
2890
|
infoText += `\n\n💡 Next steps:`;
|
|
2865
|
-
infoText += `\n • tap(text="Button Label") —
|
|
2866
|
-
infoText += `\n • tap(testID="id") or tap(component="Name") —
|
|
2867
|
-
infoText += `\n • tap(x=<px>, y=<px>) — use
|
|
2868
|
-
infoText += `\n • inspect_component("ComponentName") — inspect a component from the layout
|
|
2891
|
+
infoText += `\n • tap(text="Button Label") — when text is exact and unique`;
|
|
2892
|
+
infoText += `\n • tap(testID="id") or tap(component="Name") — when you know the identifier`;
|
|
2893
|
+
infoText += `\n • tap(x=<px>, y=<px>) — use coordinates from the pressable elements list above (reliable for icons and ambiguous elements)`;
|
|
2894
|
+
infoText += `\n • inspect_component("ComponentName") — inspect a component from the layout`;
|
|
2869
2895
|
}
|
|
2870
2896
|
else {
|
|
2871
2897
|
infoText += `\n\n💡 Next steps:`;
|
|
@@ -3343,7 +3369,7 @@ registerToolWithTelemetry("list_ios_simulators", {
|
|
|
3343
3369
|
});
|
|
3344
3370
|
// Tool: iOS screenshot
|
|
3345
3371
|
registerToolWithTelemetry("ios_screenshot", {
|
|
3346
|
-
description: "Take a screenshot from an iOS simulator. Returns the image
|
|
3372
|
+
description: "Take a screenshot from an iOS simulator. Returns the image plus two lists: (1) pressable elements — the tappable components on screen with ready-to-use pixel tap coordinates, testIDs, and labels; (2) screen layout — all visible React components for context. Prefer tap(text=\"...\") when text is exact and unique; otherwise use tap(x, y) with coordinates from the pressables list — this is the most reliable way to tap icons or visually-identified elements. Use component names from the layout for inspect_component/find_components.",
|
|
3347
3373
|
inputSchema: {
|
|
3348
3374
|
outputPath: z
|
|
3349
3375
|
.string()
|
|
@@ -3435,6 +3461,26 @@ registerToolWithTelemetry("ios_screenshot", {
|
|
|
3435
3461
|
catch {
|
|
3436
3462
|
// Non-fatal: screenshot works without layout enrichment
|
|
3437
3463
|
}
|
|
3464
|
+
// Enrich with pressable elements (filtered list of tappable components, converted to screenshot pixel coords)
|
|
3465
|
+
let pressablesText = null;
|
|
3466
|
+
try {
|
|
3467
|
+
const pressables = await getPressableElements({});
|
|
3468
|
+
if (pressables.success && pressables.parsedElements && pressables.parsedElements.length > 0) {
|
|
3469
|
+
const screenshotScale = result.scaleFactor || 1;
|
|
3470
|
+
pressablesText = pressables.parsedElements.map((el) => {
|
|
3471
|
+
const px = Math.round((el.center.x * scaleFactor) / screenshotScale);
|
|
3472
|
+
const py = Math.round((el.center.y * scaleFactor) / screenshotScale);
|
|
3473
|
+
const label = el.accessibilityLabel || el.text || el.testID || el.component;
|
|
3474
|
+
const idPart = el.testID ? ` testID="${el.testID}"` : "";
|
|
3475
|
+
const kindPart = el.isInput ? " [input]" : "";
|
|
3476
|
+
const wrapPart = el.isWrapper ? " [wrapper — skip]" : "";
|
|
3477
|
+
return ` (${px}, ${py}) ${el.component}: "${label}"${idPart}${kindPart}${wrapPart}`;
|
|
3478
|
+
}).join("\n");
|
|
3479
|
+
}
|
|
3480
|
+
}
|
|
3481
|
+
catch {
|
|
3482
|
+
// Non-fatal: screenshot works without pressables enrichment
|
|
3483
|
+
}
|
|
3438
3484
|
let infoText = `Screenshot captured (${pixelWidth}x${pixelHeight} pixels)`;
|
|
3439
3485
|
infoText += `\n📱 iOS screen: ${pointWidth}x${pointHeight} points (${scaleFactor}x scale)`;
|
|
3440
3486
|
infoText += `\n📐 tap() handles pixel-to-point conversion automatically — pass pixel coords from this image directly`;
|
|
@@ -3442,14 +3488,20 @@ registerToolWithTelemetry("ios_screenshot", {
|
|
|
3442
3488
|
if (result.scaleFactor && result.scaleFactor > 1) {
|
|
3443
3489
|
infoText += `\n🖼️ Image was scaled down to fit API limits (scale: ${result.scaleFactor.toFixed(3)})`;
|
|
3444
3490
|
}
|
|
3491
|
+
if (pressablesText) {
|
|
3492
|
+
infoText += `\n\n🎯 Pressable elements (ready-to-tap, coordinates in screenshot pixels):`;
|
|
3493
|
+
infoText += `\n${pressablesText}`;
|
|
3494
|
+
}
|
|
3445
3495
|
if (layoutText) {
|
|
3446
|
-
infoText += `\n\n📋 Screen Layout (components
|
|
3496
|
+
infoText += `\n\n📋 Screen Layout (all components, tap coordinates in pixels):`;
|
|
3447
3497
|
infoText += `\n${layoutText}`;
|
|
3498
|
+
}
|
|
3499
|
+
if (pressablesText || layoutText) {
|
|
3448
3500
|
infoText += `\n\n💡 Next steps:`;
|
|
3449
|
-
infoText += `\n • tap(text="Button Label") —
|
|
3450
|
-
infoText += `\n • tap(testID="id") or tap(component="Name") —
|
|
3451
|
-
infoText += `\n • tap(x=<px>, y=<px>) — use
|
|
3452
|
-
infoText += `\n • inspect_component("ComponentName") — inspect a component from the layout
|
|
3501
|
+
infoText += `\n • tap(text="Button Label") — when text is exact and unique`;
|
|
3502
|
+
infoText += `\n • tap(testID="id") or tap(component="Name") — when you know the identifier`;
|
|
3503
|
+
infoText += `\n • tap(x=<px>, y=<px>) — use coordinates from the pressable elements list above (reliable for icons and ambiguous elements)`;
|
|
3504
|
+
infoText += `\n • inspect_component("ComponentName") — inspect a component from the layout`;
|
|
3453
3505
|
}
|
|
3454
3506
|
else {
|
|
3455
3507
|
infoText += `\n\n💡 Next steps:`;
|