react-native-ai-debugger 1.10.9 → 1.10.11

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.
Files changed (49) hide show
  1. package/build/__tests__/setup.js +11 -5
  2. package/build/__tests__/setup.js.map +1 -1
  3. package/build/__tests__/unit/iconSemantics.test.d.ts +2 -0
  4. package/build/__tests__/unit/iconSemantics.test.d.ts.map +1 -0
  5. package/build/__tests__/unit/iconSemantics.test.js +80 -0
  6. package/build/__tests__/unit/iconSemantics.test.js.map +1 -0
  7. package/build/__tests__/unit/screenState.test.d.ts +2 -0
  8. package/build/__tests__/unit/screenState.test.d.ts.map +1 -0
  9. package/build/__tests__/unit/screenState.test.js +186 -0
  10. package/build/__tests__/unit/screenState.test.js.map +1 -0
  11. package/build/core/connection.d.ts.map +1 -1
  12. package/build/core/connection.js +57 -2
  13. package/build/core/connection.js.map +1 -1
  14. package/build/core/debugGlobals.d.ts.map +1 -1
  15. package/build/core/debugGlobals.js +29 -0
  16. package/build/core/debugGlobals.js.map +1 -1
  17. package/build/core/executor.d.ts +1 -0
  18. package/build/core/executor.d.ts.map +1 -1
  19. package/build/core/executor.js +1 -0
  20. package/build/core/executor.js.map +1 -1
  21. package/build/core/guides.js +5 -5
  22. package/build/core/iconSemantics.d.ts +18 -0
  23. package/build/core/iconSemantics.d.ts.map +1 -0
  24. package/build/core/iconSemantics.js +114 -0
  25. package/build/core/iconSemantics.js.map +1 -0
  26. package/build/core/index.d.ts +3 -1
  27. package/build/core/index.d.ts.map +1 -1
  28. package/build/core/index.js +3 -1
  29. package/build/core/index.js.map +1 -1
  30. package/build/core/pressables.d.ts +2 -0
  31. package/build/core/pressables.d.ts.map +1 -1
  32. package/build/core/pressables.js +51 -21
  33. package/build/core/pressables.js.map +1 -1
  34. package/build/core/screenState.d.ts +98 -0
  35. package/build/core/screenState.d.ts.map +1 -0
  36. package/build/core/screenState.js +1120 -0
  37. package/build/core/screenState.js.map +1 -0
  38. package/build/core/types.d.ts +1 -0
  39. package/build/core/types.d.ts.map +1 -1
  40. package/build/tools/componentTools.d.ts.map +1 -1
  41. package/build/tools/componentTools.js +48 -5
  42. package/build/tools/componentTools.js.map +1 -1
  43. package/build/tools/metaTools.d.ts.map +1 -1
  44. package/build/tools/metaTools.js +6 -5
  45. package/build/tools/metaTools.js.map +1 -1
  46. package/build/tools/screenshotTools.d.ts.map +1 -1
  47. package/build/tools/screenshotTools.js +105 -40
  48. package/build/tools/screenshotTools.js.map +1 -1
  49. package/package.json +1 -1
@@ -1,9 +1,15 @@
1
1
  import { afterEach } from "@jest/globals";
2
2
  afterEach(async () => {
3
- const { cancelAllReconnectionTimers, clearAllConnectionState } = await import("../core/connectionState.js");
4
- const { pendingExecutions } = await import("../core/state.js");
5
- cancelAllReconnectionTimers();
6
- clearAllConnectionState();
7
- pendingExecutions.clear();
3
+ try {
4
+ const { cancelAllReconnectionTimers, clearAllConnectionState } = await import("../core/connectionState.js");
5
+ const { pendingExecutions } = await import("../core/state.js");
6
+ cancelAllReconnectionTimers();
7
+ clearAllConnectionState();
8
+ pendingExecutions.clear();
9
+ }
10
+ catch (e) {
11
+ // Silently ignore import errors in test environment
12
+ // Some core modules use import.meta which may not work in all Jest contexts
13
+ }
8
14
  });
9
15
  //# sourceMappingURL=setup.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/__tests__/setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,SAAS,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,EAAE,2BAA2B,EAAE,uBAAuB,EAAE,GAAG,MAAM,MAAM,CACzE,4BAA4B,CAC/B,CAAC;IACF,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IAC/D,2BAA2B,EAAE,CAAC;IAC9B,uBAAuB,EAAE,CAAC;IAC1B,iBAAiB,CAAC,KAAK,EAAE,CAAC;AAC9B,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/__tests__/setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,SAAS,CAAC,KAAK,IAAI,EAAE;IACjB,IAAI,CAAC;QACD,MAAM,EAAE,2BAA2B,EAAE,uBAAuB,EAAE,GAAG,MAAM,MAAM,CACzE,4BAA4B,CAC/B,CAAC;QACF,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAC/D,2BAA2B,EAAE,CAAC;QAC9B,uBAAuB,EAAE,CAAC;QAC1B,iBAAiB,CAAC,KAAK,EAAE,CAAC;IAC9B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACT,oDAAoD;QACpD,4EAA4E;IAChF,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=iconSemantics.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iconSemantics.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/iconSemantics.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,80 @@
1
+ import { describe, it, expect } from "@jest/globals";
2
+ import { iconSemanticHint, iconLabel } from "../../core/iconSemantics.js";
3
+ import { applyIconHintToLabel } from "../../core/screenState.js";
4
+ describe("iconSemanticHint", () => {
5
+ it("maps chevron/arrow + direction composites", () => {
6
+ expect(iconSemanticHint("SvgChevronBackward")).toBe("possibly back button");
7
+ expect(iconSemanticHint("ChevronLeft")).toBe("possibly back button");
8
+ expect(iconSemanticHint("ArrowRightIcon")).toBe("possibly forward/next button");
9
+ expect(iconSemanticHint("CaretDown")).toBe("possibly expand/open button");
10
+ expect(iconSemanticHint("chevron-up")).toBe("possibly collapse button");
11
+ });
12
+ it("maps standalone icon keywords", () => {
13
+ expect(iconSemanticHint("SvgClose")).toBe("possibly close button");
14
+ expect(iconSemanticHint("CheckboxOutline")).toBe("possibly checkbox");
15
+ expect(iconSemanticHint("RadioOn")).toBe("possibly radio button");
16
+ expect(iconSemanticHint("BackIcon")).toBe("possibly back button");
17
+ expect(iconSemanticHint("IconTrashCan")).toBe("possibly delete button");
18
+ expect(iconSemanticHint("HamburgerMenu")).toBe("possibly menu button");
19
+ expect(iconSemanticHint("SearchOutline")).toBe("possibly search button");
20
+ expect(iconSemanticHint("PlusCircle")).toBe("possibly add button");
21
+ expect(iconSemanticHint("DotsVertical")).toBe("possibly more-options button");
22
+ });
23
+ it("prefers checkbox over check", () => {
24
+ expect(iconSemanticHint("SvgCheckbox")).toBe("possibly checkbox");
25
+ expect(iconSemanticHint("SvgCheckmark")).toBe("possibly confirm/check button");
26
+ });
27
+ it("matches whole words only — no substring false positives", () => {
28
+ expect(iconSemanticHint("FeedbackForm")).toBeNull();
29
+ expect(iconSemanticHint("BackgroundView")).toBeNull();
30
+ expect(iconSemanticHint("Checkout")).toBeNull();
31
+ expect(iconSemanticHint("StarterKit")).toBeNull();
32
+ });
33
+ it("returns null for non-icon names and empty input", () => {
34
+ expect(iconSemanticHint("FloatingHeader")).toBeNull();
35
+ expect(iconSemanticHint("SneakerCard")).toBeNull();
36
+ expect(iconSemanticHint(null)).toBeNull();
37
+ expect(iconSemanticHint(undefined)).toBeNull();
38
+ expect(iconSemanticHint("")).toBeNull();
39
+ });
40
+ });
41
+ describe("iconLabel", () => {
42
+ it("combines the icon component name with the hint", () => {
43
+ expect(iconLabel("FloatingHeader", "SvgChevronBackward")).toBe("SvgChevronBackward — possibly back button");
44
+ });
45
+ it("falls back to the component name when no icon child is known", () => {
46
+ expect(iconLabel("CloseIcon", null)).toBe("CloseIcon — possibly close button");
47
+ });
48
+ it("returns null when neither name carries icon semantics", () => {
49
+ expect(iconLabel("FloatingHeader", null)).toBeNull();
50
+ expect(iconLabel("FloatingHeader", "FancyDecoration")).toBeNull();
51
+ });
52
+ });
53
+ describe("applyIconHintToLabel", () => {
54
+ function pressable(overrides = {}) {
55
+ return {
56
+ label: "[FloatingHeader]",
57
+ center: { x: 40, y: 100 },
58
+ bounds: { x: 16, y: 76, width: 48, height: 48 },
59
+ testID: null,
60
+ ...overrides,
61
+ };
62
+ }
63
+ it("rewrites a fallback label using the icon hint", () => {
64
+ const p = applyIconHintToLabel(pressable({ icon: "SvgChevronBackward" }));
65
+ expect(p.label).toBe("[SvgChevronBackward — possibly back button]");
66
+ });
67
+ it("keeps the existing label when the icon name has no semantics", () => {
68
+ const p = applyIconHintToLabel(pressable({ icon: "FancyDecoration" }));
69
+ expect(p.label).toBe("[FloatingHeader]");
70
+ });
71
+ it("uses the icon name when there is no label at all", () => {
72
+ const p = applyIconHintToLabel(pressable({ label: null, icon: "FancyDecoration" }));
73
+ expect(p.label).toBe("[FancyDecoration]");
74
+ });
75
+ it("never touches text/a11y labels (icon is null for those)", () => {
76
+ const p = applyIconHintToLabel(pressable({ label: "Submit", icon: null }));
77
+ expect(p.label).toBe("Submit");
78
+ });
79
+ });
80
+ //# sourceMappingURL=iconSemantics.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iconSemantics.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/iconSemantics.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=screenState.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screenState.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/screenState.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,186 @@
1
+ import { describe, it, expect } from "@jest/globals";
2
+ import { markPressablesCoveredByOverlay, parseScreenStateResponse, formatScreenStateSummary, describePressHandler, describePropHandlers, } from "../../core/screenState.js";
3
+ function pressable(overrides = {}) {
4
+ return {
5
+ label: "Button",
6
+ center: { x: 100, y: 100 },
7
+ bounds: { x: 80, y: 80, width: 40, height: 40 },
8
+ testID: null,
9
+ ...overrides,
10
+ };
11
+ }
12
+ describe("markPressablesCoveredByOverlay", () => {
13
+ const overlay = { x: 0, y: 400, width: 375, height: 300 };
14
+ it("does not flag pressable fully above the overlay", () => {
15
+ const p = pressable({ bounds: { x: 10, y: 50, width: 100, height: 44 } });
16
+ const result = markPressablesCoveredByOverlay([p], overlay);
17
+ expect(result[0].blockedByOverlay).toBeUndefined();
18
+ });
19
+ it("flags pressable fully inside the overlay bounds", () => {
20
+ const p = pressable({ bounds: { x: 50, y: 450, width: 100, height: 44 } });
21
+ const result = markPressablesCoveredByOverlay([p], overlay);
22
+ expect(result[0].blockedByOverlay).toBe(true);
23
+ });
24
+ it("does not flag pressable that partially overlaps (only fully covered ones are blocked)", () => {
25
+ const p = pressable({ bounds: { x: 50, y: 380, width: 100, height: 60 } });
26
+ const result = markPressablesCoveredByOverlay([p], overlay);
27
+ expect(result[0].blockedByOverlay).toBeUndefined();
28
+ });
29
+ it("handles empty pressables list", () => {
30
+ expect(markPressablesCoveredByOverlay([], overlay)).toHaveLength(0);
31
+ });
32
+ });
33
+ describe("parseScreenStateResponse", () => {
34
+ it("returns null for null input", () => {
35
+ expect(parseScreenStateResponse(null)).toBeNull();
36
+ });
37
+ it("returns null when response has error field", () => {
38
+ expect(parseScreenStateResponse({ error: "No hook found" })).toBeNull();
39
+ });
40
+ it("parses a full response with route, overlays, and pressables", () => {
41
+ const raw = {
42
+ route: { name: "ProductDetails", params: { productId: "123" }, stack: ["Home", "ProductDetails"] },
43
+ overlays: [
44
+ {
45
+ type: "BottomSheet",
46
+ title: "Select Size",
47
+ pressables: [
48
+ { label: "S", center: { x: 70, y: 582 }, bounds: { x: 40, y: 560, width: 60, height: 44 }, testID: null },
49
+ ],
50
+ },
51
+ ],
52
+ pressables: [
53
+ { label: "Back", center: { x: 38, y: 78 }, bounds: { x: 16, y: 56, width: 44, height: 44 }, testID: null },
54
+ ],
55
+ };
56
+ const result = parseScreenStateResponse(raw);
57
+ expect(result).not.toBeNull();
58
+ expect(result.route.name).toBe("ProductDetails");
59
+ expect(result.route.stack).toEqual(["Home", "ProductDetails"]);
60
+ expect(result.overlays).toHaveLength(1);
61
+ expect(result.overlays[0].type).toBe("BottomSheet");
62
+ expect(result.overlays[0].pressables).toHaveLength(1);
63
+ expect(result.pressables).toHaveLength(1);
64
+ expect(result.pressables[0].label).toBe("Back");
65
+ });
66
+ it("parses a response with null route (no navigation library)", () => {
67
+ const raw = { route: null, overlays: [], pressables: [] };
68
+ const result = parseScreenStateResponse(raw);
69
+ expect(result).not.toBeNull();
70
+ expect(result.route).toBeNull();
71
+ expect(result.overlays).toHaveLength(0);
72
+ });
73
+ it("defaults overlays and pressables to empty arrays when missing", () => {
74
+ const raw = { route: null };
75
+ const result = parseScreenStateResponse(raw);
76
+ expect(result.overlays).toEqual([]);
77
+ expect(result.pressables).toEqual([]);
78
+ });
79
+ });
80
+ describe("describePressHandler", () => {
81
+ it("returns named handlers as calls", () => {
82
+ expect(describePressHandler({ n: "handleSubmit", s: "" })).toBe("handleSubmit()");
83
+ expect(describePressHandler({ n: "startProcessing", s: "function startProcessing() {…}" })).toBe("startProcessing()");
84
+ });
85
+ it("strips the 'bound ' prefix", () => {
86
+ expect(describePressHandler({ n: "bound goBack", s: "" })).toBe("goBack()");
87
+ });
88
+ it("rejects generic and minified names, falling back to source", () => {
89
+ expect(describePressHandler({ n: "onPress", s: "() => setAccepted(prev => !prev)" })).toBe("{() => setAccepted(prev => !prev)}");
90
+ expect(describePressHandler({ n: "t12", s: "" })).toBeNull();
91
+ expect(describePressHandler({ n: "anonymous", s: "" })).toBeNull();
92
+ expect(describePressHandler({ n: "e", s: "" })).toBeNull();
93
+ });
94
+ it("truncates long source snippets", () => {
95
+ const longSrc = "() => " + "x".repeat(100);
96
+ const out = describePressHandler({ n: "", s: longSrc });
97
+ expect(out).toContain("…");
98
+ expect(out.length).toBeLessThan(80);
99
+ });
100
+ it("returns null for bytecode bundles (source stripped in-app) and bad input", () => {
101
+ expect(describePressHandler({ n: "", s: "" })).toBeNull();
102
+ expect(describePressHandler(null)).toBeNull();
103
+ expect(describePressHandler(undefined)).toBeNull();
104
+ });
105
+ });
106
+ describe("describePropHandlers", () => {
107
+ it("prefers the identity-matched prop and shows its named handler", () => {
108
+ const raw = [
109
+ { p: "onRightPress", n: "", same: false },
110
+ { p: "onBack", n: "goBack", same: true },
111
+ ];
112
+ expect(describePropHandlers(raw)).toBe("onBack=goBack()");
113
+ });
114
+ it("reports the prop route when the matched handler is anonymous", () => {
115
+ expect(describePropHandlers([{ p: "onBack", n: "", same: true }])).toBe("onPress→onBack");
116
+ });
117
+ it("suppresses a nameless plain onPress prop (adds nothing)", () => {
118
+ expect(describePropHandlers([{ p: "onPress", n: "", same: true }])).toBeNull();
119
+ expect(describePropHandlers([{ p: "onPress", n: "onPress", same: true }])).toBeNull();
120
+ });
121
+ it("uses the only candidate when there is no identity match", () => {
122
+ expect(describePropHandlers([{ p: "onSelect", n: "", same: false }])).toBe("onPress→onSelect");
123
+ });
124
+ it("returns null on ambiguity (several candidates, none identity-matched)", () => {
125
+ const raw = [
126
+ { p: "onBack", n: "", same: false },
127
+ { p: "onRightPress", n: "", same: false },
128
+ ];
129
+ expect(describePropHandlers(raw)).toBeNull();
130
+ });
131
+ it("returns null for empty or malformed input", () => {
132
+ expect(describePropHandlers(null)).toBeNull();
133
+ expect(describePropHandlers([])).toBeNull();
134
+ expect(describePropHandlers("nope")).toBeNull();
135
+ });
136
+ });
137
+ describe("formatScreenStateSummary", () => {
138
+ const state = {
139
+ route: { name: "Checkout", params: { id: "7" }, stack: ["Tabs", "Cart", "Checkout"] },
140
+ overlays: [],
141
+ pressables: [
142
+ pressable({
143
+ label: "Send",
144
+ component: "Button",
145
+ center: { x: 210, y: 838 },
146
+ bounds: { x: 20, y: 810, width: 380, height: 56 },
147
+ }),
148
+ pressable({
149
+ label: "[CheckBox — possibly confirm/check button]",
150
+ component: "CheckBox",
151
+ nearbyText: "Skip verification.",
152
+ center: { x: 31, y: 719 },
153
+ bounds: { x: 20, y: 708, width: 22, height: 22 },
154
+ }),
155
+ ],
156
+ };
157
+ it("renders route, params, component tags, labels, nearby text, and frames", () => {
158
+ const out = formatScreenStateSummary(state);
159
+ expect(out).toContain('📍 Currently focused screen: "Checkout" [navigation stack: Tabs > Cart > Checkout]');
160
+ expect(out).toContain('route params: {"id":"7"}');
161
+ expect(out).toContain('(210, 838) <Button /> "Send" frame:(20,810 380x56)');
162
+ expect(out).toContain('near "Skip verification."');
163
+ });
164
+ it("applies the coordinate converter to centers and frames", () => {
165
+ const out = formatScreenStateSummary(state, (p) => ({
166
+ center: { x: p.center.x * 2, y: p.center.y * 2 },
167
+ frame: { x: p.bounds.x * 2, y: p.bounds.y * 2, width: p.bounds.width * 2, height: p.bounds.height * 2 },
168
+ }));
169
+ expect(out).toContain('(420, 1676) <Button /> "Send" frame:(40,1620 760x112)');
170
+ });
171
+ it("groups overlay pressables and lists blocked root pressables separately", () => {
172
+ const withOverlay = {
173
+ route: null,
174
+ overlays: [{ type: "BottomSheet", title: null, pressables: [pressable({ label: "Submit" })] }],
175
+ pressables: [pressable({ label: "Send", blockedByOverlay: true })],
176
+ };
177
+ const out = formatScreenStateSummary(withOverlay);
178
+ expect(out).toContain("📍 Currently focused screen: unknown");
179
+ expect(out).toContain("🔲 BottomSheet:");
180
+ expect(out).toContain('"Submit"');
181
+ expect(out).toContain("🎯 Root pressables: (none reachable)");
182
+ expect(out).toContain("🚫 Blocked by overlay");
183
+ expect(out).toContain('"Send"');
184
+ });
185
+ });
186
+ //# sourceMappingURL=screenState.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screenState.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/screenState.test.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/core/connection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/core/connection.ts"],"names":[],"mappings":"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"}
@@ -20,6 +20,15 @@ const pendingNetworkEnableIds = new Set();
20
20
  const pendingSdkProbeIds = new Map(); // msgId -> appKey
21
21
  const SDK_PROBE_INITIAL_DELAY_MS = 200;
22
22
  const SDK_PROBE_INTERVAL_MS = 3000;
23
+ // Consecutive SDK-absent probes required to flip sdkPresent true→false.
24
+ // Hysteresis against the post-reload window where the JS context exists but
25
+ // the SDK's init() hasn't re-run yet (see ConnectedApp.sdkMissCount).
26
+ const SDK_ABSENCE_CONFIRM_COUNT = 2;
27
+ // Fast re-probe schedule after a context is (re)created, so the SDK is
28
+ // re-detected within a few hundred ms instead of waiting up to a full
29
+ // SDK_PROBE_INTERVAL_MS tick. Covers reloads not driven by reload_app
30
+ // (shake-to-reload, Metro "r").
31
+ const SDK_REPROBE_DELAYS_MS = [200, 500, 1000, 2000];
23
32
  function sendSdkProbe(ws, appKey) {
24
33
  if (ws.readyState !== WebSocket.OPEN)
25
34
  return;
@@ -59,6 +68,20 @@ function startSdkProbeLoop(ws, appKey) {
59
68
  clearInterval(interval);
60
69
  });
61
70
  }
71
+ // Fire a burst of SDK probes on the heels of a (re)created execution context.
72
+ // After a reload the context is recreated but the SDK's init() re-runs slightly
73
+ // later; without this, sdkPresent only recovers on the next 3s interval tick,
74
+ // widening the window where get_network_requests falls off the SDK buffer.
75
+ function scheduleFastSdkReprobe(ws, appKey) {
76
+ for (const delay of SDK_REPROBE_DELAYS_MS) {
77
+ const t = setTimeout(() => {
78
+ if (!connectedApps.has(appKey) || ws.readyState !== WebSocket.OPEN)
79
+ return;
80
+ sendSdkProbe(ws, appKey);
81
+ }, delay);
82
+ ws.once("close", () => clearTimeout(t));
83
+ }
84
+ }
62
85
  // Suppress auto-reconnection for intentionally disconnected devices
63
86
  const reconnectionSuppressed = new Set();
64
87
  /**
@@ -528,8 +551,25 @@ export function handleCDPMessage(message, device, ws) {
528
551
  const result = message.result?.result;
529
552
  const present = result?.value === true;
530
553
  const wasPresent = app.sdkPresent === true;
531
- app.sdkPresent = present;
532
- if (present !== wasPresent) {
554
+ // Hysteresis on the true→false edge: tolerate transient SDK
555
+ // absence right after a reload (context recreated, init() not
556
+ // re-run yet) so we don't restore duplicate-prone CDP/interceptor
557
+ // writes and bounce get_network_requests off the SDK buffer.
558
+ let nextPresent = present;
559
+ if (!present && wasPresent) {
560
+ app.sdkMissCount = (app.sdkMissCount ?? 0) + 1;
561
+ if (app.sdkMissCount < SDK_ABSENCE_CONFIRM_COUNT) {
562
+ nextPresent = true; // hold "present" until absence is confirmed
563
+ }
564
+ else {
565
+ app.sdkMissCount = 0;
566
+ }
567
+ }
568
+ else {
569
+ app.sdkMissCount = 0;
570
+ }
571
+ app.sdkPresent = nextPresent;
572
+ if (nextPresent !== wasPresent) {
533
573
  console.error(`[execbro] SDK ${present ? "detected" : "no longer detected"} on ${app.deviceInfo.title}; CDP/JS-interceptor buffer writes ${present ? "suppressed" : "restored"}`);
534
574
  // Toggle the in-app interceptor's emit flag so it stops
535
575
  // (or resumes) producing console.debug lines and CDP
@@ -650,6 +690,17 @@ export function handleCDPMessage(message, device, ws) {
650
690
  if (nApp?.sdkPresent) {
651
691
  return;
652
692
  }
693
+ // An arriving Network.requestWillBeSent is proof the CDP Network domain
694
+ // is active. Some backends (e.g. RN 0.85 Bridgeless/Hermes) enable the
695
+ // domain but never send a response to Network.enable, so the
696
+ // response-based detection above never fires and cdpNetworkSupported
697
+ // stays undefined — leaving the JS interceptor un-suppressed and every
698
+ // request double-captured (CDP + interceptor). Mark support here so the
699
+ // interceptor dedup guard (see Runtime.consoleAPICalled handler) trips.
700
+ if (nApp && !nApp.cdpNetworkSupported) {
701
+ nApp.cdpNetworkSupported = true;
702
+ console.error(`[execbro] CDP Network domain active (detected via requestWillBeSent on ${nApp.deviceInfo.title})`);
703
+ }
653
704
  const params = message.params;
654
705
  const request = {
655
706
  requestId: params.requestId,
@@ -717,6 +768,10 @@ export function handleCDPMessage(message, device, ws) {
717
768
  injectNetworkInterceptor(ctxApp.ws);
718
769
  const nEnableId = sendNetworkEnable(ctxApp.ws);
719
770
  pendingNetworkEnableIds.add(nEnableId);
771
+ // The context was just recreated (e.g. reload). Re-probe the SDK
772
+ // quickly so sdkPresent re-establishes within a few hundred ms
773
+ // instead of on the next 3s interval tick.
774
+ scheduleFastSdkReprobe(ctxApp.ws, appKey);
720
775
  }
721
776
  }
722
777
  // Handle Runtime.executionContextDestroyed