react-native-ai-debugger 1.10.24 → 1.11.0

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 (202) hide show
  1. package/README.md +1 -1
  2. package/build/__tests__/helpers/fake-cdp-server.d.ts +9 -0
  3. package/build/__tests__/helpers/fake-cdp-server.d.ts.map +1 -1
  4. package/build/__tests__/helpers/fake-cdp-server.js +20 -2
  5. package/build/__tests__/helpers/fake-cdp-server.js.map +1 -1
  6. package/build/__tests__/integration/connection-health.test.js +8 -1
  7. package/build/__tests__/integration/connection-health.test.js.map +1 -1
  8. package/build/__tests__/integration/native-logs.test.d.ts +2 -0
  9. package/build/__tests__/integration/native-logs.test.d.ts.map +1 -0
  10. package/build/__tests__/integration/native-logs.test.js +39 -0
  11. package/build/__tests__/integration/native-logs.test.js.map +1 -0
  12. package/build/__tests__/integration/socket-close-midflight.test.d.ts +2 -0
  13. package/build/__tests__/integration/socket-close-midflight.test.d.ts.map +1 -0
  14. package/build/__tests__/integration/socket-close-midflight.test.js +106 -0
  15. package/build/__tests__/integration/socket-close-midflight.test.js.map +1 -0
  16. package/build/__tests__/integration/stale-target-probe.test.d.ts +2 -0
  17. package/build/__tests__/integration/stale-target-probe.test.d.ts.map +1 -0
  18. package/build/__tests__/integration/stale-target-probe.test.js +85 -0
  19. package/build/__tests__/integration/stale-target-probe.test.js.map +1 -0
  20. package/build/__tests__/unit/clearLogsNative.test.d.ts +2 -0
  21. package/build/__tests__/unit/clearLogsNative.test.d.ts.map +1 -0
  22. package/build/__tests__/unit/clearLogsNative.test.js +43 -0
  23. package/build/__tests__/unit/clearLogsNative.test.js.map +1 -0
  24. package/build/__tests__/unit/componentFormatNaming.test.d.ts +2 -0
  25. package/build/__tests__/unit/componentFormatNaming.test.d.ts.map +1 -0
  26. package/build/__tests__/unit/componentFormatNaming.test.js +32 -0
  27. package/build/__tests__/unit/componentFormatNaming.test.js.map +1 -0
  28. package/build/__tests__/unit/deviceResolution.test.d.ts +2 -0
  29. package/build/__tests__/unit/deviceResolution.test.d.ts.map +1 -0
  30. package/build/__tests__/unit/deviceResolution.test.js +108 -0
  31. package/build/__tests__/unit/deviceResolution.test.js.map +1 -0
  32. package/build/__tests__/unit/executor.test.js +48 -12
  33. package/build/__tests__/unit/executor.test.js.map +1 -1
  34. package/build/__tests__/unit/getLogsEmptyContract.test.d.ts +2 -0
  35. package/build/__tests__/unit/getLogsEmptyContract.test.d.ts.map +1 -0
  36. package/build/__tests__/unit/getLogsEmptyContract.test.js +112 -0
  37. package/build/__tests__/unit/getLogsEmptyContract.test.js.map +1 -0
  38. package/build/__tests__/unit/getLogsNativeSource.test.d.ts +2 -0
  39. package/build/__tests__/unit/getLogsNativeSource.test.d.ts.map +1 -0
  40. package/build/__tests__/unit/getLogsNativeSource.test.js +138 -0
  41. package/build/__tests__/unit/getLogsNativeSource.test.js.map +1 -0
  42. package/build/__tests__/unit/jsLogEvents.test.d.ts +2 -0
  43. package/build/__tests__/unit/jsLogEvents.test.d.ts.map +1 -0
  44. package/build/__tests__/unit/jsLogEvents.test.js +58 -0
  45. package/build/__tests__/unit/jsLogEvents.test.js.map +1 -0
  46. package/build/__tests__/unit/logDiagnosis.test.d.ts +2 -0
  47. package/build/__tests__/unit/logDiagnosis.test.d.ts.map +1 -0
  48. package/build/__tests__/unit/logDiagnosis.test.js +81 -0
  49. package/build/__tests__/unit/logDiagnosis.test.js.map +1 -0
  50. package/build/__tests__/unit/logEventFormat.test.d.ts +2 -0
  51. package/build/__tests__/unit/logEventFormat.test.d.ts.map +1 -0
  52. package/build/__tests__/unit/logEventFormat.test.js +210 -0
  53. package/build/__tests__/unit/logEventFormat.test.js.map +1 -0
  54. package/build/__tests__/unit/logEvents.test.d.ts +2 -0
  55. package/build/__tests__/unit/logEvents.test.d.ts.map +1 -0
  56. package/build/__tests__/unit/logEvents.test.js +118 -0
  57. package/build/__tests__/unit/logEvents.test.js.map +1 -0
  58. package/build/__tests__/unit/logGrouping.test.d.ts +2 -0
  59. package/build/__tests__/unit/logGrouping.test.d.ts.map +1 -0
  60. package/build/__tests__/unit/logGrouping.test.js +104 -0
  61. package/build/__tests__/unit/logGrouping.test.js.map +1 -0
  62. package/build/__tests__/unit/logOwnership.test.d.ts +2 -0
  63. package/build/__tests__/unit/logOwnership.test.d.ts.map +1 -0
  64. package/build/__tests__/unit/logOwnership.test.js +118 -0
  65. package/build/__tests__/unit/logOwnership.test.js.map +1 -0
  66. package/build/__tests__/unit/logRelevance.test.d.ts +2 -0
  67. package/build/__tests__/unit/logRelevance.test.d.ts.map +1 -0
  68. package/build/__tests__/unit/logRelevance.test.js +30 -0
  69. package/build/__tests__/unit/logRelevance.test.js.map +1 -0
  70. package/build/__tests__/unit/logSourceAndroid.test.d.ts +2 -0
  71. package/build/__tests__/unit/logSourceAndroid.test.d.ts.map +1 -0
  72. package/build/__tests__/unit/logSourceAndroid.test.js +61 -0
  73. package/build/__tests__/unit/logSourceAndroid.test.js.map +1 -0
  74. package/build/__tests__/unit/logSourceIos.test.d.ts +2 -0
  75. package/build/__tests__/unit/logSourceIos.test.d.ts.map +1 -0
  76. package/build/__tests__/unit/logSourceIos.test.js +64 -0
  77. package/build/__tests__/unit/logSourceIos.test.js.map +1 -0
  78. package/build/__tests__/unit/logs.test.js +23 -0
  79. package/build/__tests__/unit/logs.test.js.map +1 -1
  80. package/build/__tests__/unit/nativeLogs.test.d.ts +2 -0
  81. package/build/__tests__/unit/nativeLogs.test.d.ts.map +1 -0
  82. package/build/__tests__/unit/nativeLogs.test.js +230 -0
  83. package/build/__tests__/unit/nativeLogs.test.js.map +1 -0
  84. package/build/__tests__/unit/pendingExecutions.test.d.ts +2 -0
  85. package/build/__tests__/unit/pendingExecutions.test.d.ts.map +1 -0
  86. package/build/__tests__/unit/pendingExecutions.test.js +70 -0
  87. package/build/__tests__/unit/pendingExecutions.test.js.map +1 -0
  88. package/build/__tests__/unit/reloadAppAutoConnect.test.d.ts +2 -0
  89. package/build/__tests__/unit/reloadAppAutoConnect.test.d.ts.map +1 -0
  90. package/build/__tests__/unit/reloadAppAutoConnect.test.js +63 -0
  91. package/build/__tests__/unit/reloadAppAutoConnect.test.js.map +1 -0
  92. package/build/__tests__/unit/toolsJson.test.js +11 -0
  93. package/build/__tests__/unit/toolsJson.test.js.map +1 -1
  94. package/build/__tests__/unit/transportClassify.test.js +108 -7
  95. package/build/__tests__/unit/transportClassify.test.js.map +1 -1
  96. package/build/core/componentSearch.d.ts +1 -1
  97. package/build/core/componentSearch.d.ts.map +1 -1
  98. package/build/core/componentSearch.js +8 -8
  99. package/build/core/componentSearch.js.map +1 -1
  100. package/build/core/componentTree.d.ts +1 -1
  101. package/build/core/componentTree.d.ts.map +1 -1
  102. package/build/core/componentTree.js +8 -8
  103. package/build/core/componentTree.js.map +1 -1
  104. package/build/core/connection.d.ts +30 -0
  105. package/build/core/connection.d.ts.map +1 -1
  106. package/build/core/connection.js +97 -28
  107. package/build/core/connection.js.map +1 -1
  108. package/build/core/debugGlobals.d.ts.map +1 -1
  109. package/build/core/debugGlobals.js +89 -32
  110. package/build/core/debugGlobals.js.map +1 -1
  111. package/build/core/errors.d.ts +7 -1
  112. package/build/core/errors.d.ts.map +1 -1
  113. package/build/core/errors.js +8 -1
  114. package/build/core/errors.js.map +1 -1
  115. package/build/core/guides.d.ts.map +1 -1
  116. package/build/core/guides.js +25 -0
  117. package/build/core/guides.js.map +1 -1
  118. package/build/core/index.d.ts +0 -2
  119. package/build/core/index.d.ts.map +1 -1
  120. package/build/core/index.js +0 -2
  121. package/build/core/index.js.map +1 -1
  122. package/build/core/jsExecute.d.ts +76 -1
  123. package/build/core/jsExecute.d.ts.map +1 -1
  124. package/build/core/jsExecute.js +193 -32
  125. package/build/core/jsExecute.js.map +1 -1
  126. package/build/core/jsLogEvents.d.ts +13 -0
  127. package/build/core/jsLogEvents.d.ts.map +1 -0
  128. package/build/core/jsLogEvents.js +65 -0
  129. package/build/core/jsLogEvents.js.map +1 -0
  130. package/build/core/logDiagnosis.d.ts +65 -0
  131. package/build/core/logDiagnosis.d.ts.map +1 -0
  132. package/build/core/logDiagnosis.js +51 -0
  133. package/build/core/logDiagnosis.js.map +1 -0
  134. package/build/core/logEventFormat.d.ts +14 -0
  135. package/build/core/logEventFormat.d.ts.map +1 -0
  136. package/build/core/logEventFormat.js +85 -0
  137. package/build/core/logEventFormat.js.map +1 -0
  138. package/build/core/logEvents.d.ts +115 -0
  139. package/build/core/logEvents.d.ts.map +1 -0
  140. package/build/core/logEvents.js +146 -0
  141. package/build/core/logEvents.js.map +1 -0
  142. package/build/core/logGrouping.d.ts +17 -0
  143. package/build/core/logGrouping.d.ts.map +1 -0
  144. package/build/core/logGrouping.js +134 -0
  145. package/build/core/logGrouping.js.map +1 -0
  146. package/build/core/logOwnership.d.ts +29 -0
  147. package/build/core/logOwnership.d.ts.map +1 -0
  148. package/build/core/logOwnership.js +83 -0
  149. package/build/core/logOwnership.js.map +1 -0
  150. package/build/core/logRelevance.d.ts +13 -0
  151. package/build/core/logRelevance.d.ts.map +1 -0
  152. package/build/core/logRelevance.js +23 -0
  153. package/build/core/logRelevance.js.map +1 -0
  154. package/build/core/logSourceAndroid.d.ts +27 -0
  155. package/build/core/logSourceAndroid.d.ts.map +1 -0
  156. package/build/core/logSourceAndroid.js +89 -0
  157. package/build/core/logSourceAndroid.js.map +1 -0
  158. package/build/core/logSourceIos.d.ts +26 -0
  159. package/build/core/logSourceIos.d.ts.map +1 -0
  160. package/build/core/logSourceIos.js +119 -0
  161. package/build/core/logSourceIos.js.map +1 -0
  162. package/build/core/logs.d.ts +5 -1
  163. package/build/core/logs.d.ts.map +1 -1
  164. package/build/core/logs.js +8 -1
  165. package/build/core/logs.js.map +1 -1
  166. package/build/core/nativeLogs.d.ts +75 -0
  167. package/build/core/nativeLogs.d.ts.map +1 -0
  168. package/build/core/nativeLogs.js +260 -0
  169. package/build/core/nativeLogs.js.map +1 -0
  170. package/build/core/register.d.ts.map +1 -1
  171. package/build/core/register.js +22 -6
  172. package/build/core/register.js.map +1 -1
  173. package/build/core/screenLayout.d.ts +1 -1
  174. package/build/core/screenLayout.d.ts.map +1 -1
  175. package/build/core/screenLayout.js +3 -3
  176. package/build/core/screenLayout.js.map +1 -1
  177. package/build/core/state.d.ts +10 -0
  178. package/build/core/state.d.ts.map +1 -1
  179. package/build/core/state.js +21 -0
  180. package/build/core/state.js.map +1 -1
  181. package/build/core/types.d.ts +11 -2
  182. package/build/core/types.d.ts.map +1 -1
  183. package/build/tools/componentTools.js +6 -6
  184. package/build/tools/componentTools.js.map +1 -1
  185. package/build/tools/connectionTools.d.ts.map +1 -1
  186. package/build/tools/connectionTools.js +7 -3
  187. package/build/tools/connectionTools.js.map +1 -1
  188. package/build/tools/executionTools.js +7 -7
  189. package/build/tools/executionTools.js.map +1 -1
  190. package/build/tools/logTools.d.ts +25 -0
  191. package/build/tools/logTools.d.ts.map +1 -1
  192. package/build/tools/logTools.js +316 -132
  193. package/build/tools/logTools.js.map +1 -1
  194. package/build/tools/networkTools.d.ts.map +1 -1
  195. package/build/tools/networkTools.js +65 -54
  196. package/build/tools/networkTools.js.map +1 -1
  197. package/package.json +5 -4
  198. package/tools.json +447 -0
  199. package/build/core/format.d.ts +0 -8
  200. package/build/core/format.d.ts.map +0 -1
  201. package/build/core/format.js +0 -34
  202. package/build/core/format.js.map +0 -1
@@ -0,0 +1,118 @@
1
+ // The adversarial cases here are verbatim from a live Android 16 emulator on
2
+ // 2026-07-29. Each one defeats an obvious-but-wrong ownership rule.
3
+ import { describe, it, expect } from "@jest/globals";
4
+ import { isOwned } from "../../core/logOwnership.js";
5
+ const APP = {
6
+ deviceKey: "emulator-5554",
7
+ platform: "android",
8
+ appId: "com.rndebuggertestapp",
9
+ pid: 23325,
10
+ };
11
+ function line(over) {
12
+ return {
13
+ ts: new Date("2026-07-29T22:11:05.015Z"),
14
+ level: "info",
15
+ pid: 1,
16
+ tag: "Unknown",
17
+ message: "",
18
+ raw: "",
19
+ ...over,
20
+ };
21
+ }
22
+ describe("isOwned", () => {
23
+ it("owns a tombstone the app did not write, via its declared subject", () => {
24
+ // Written by tombstoned (pid 22617); the dead app was 17782. Pid
25
+ // matching can never work here, which is why `declared` is rule 1.
26
+ const v = isOwned(line({
27
+ pid: 22617,
28
+ tag: "DEBUG",
29
+ level: "fatal",
30
+ subject: "com.rndebuggertestapp",
31
+ message: "pid: 17782, tid: 17832 >>> com.rndebuggertestapp <<<",
32
+ }), { ...APP, pid: undefined });
33
+ expect(v).toEqual({ owned: true, reason: "declared" });
34
+ });
35
+ it("owns lines from the live pid", () => {
36
+ expect(isOwned(line({ pid: 23325, tag: "ReactNative" }), APP))
37
+ .toEqual({ owned: true, reason: "pid" });
38
+ });
39
+ it("owns an ANR reported by ActivityManager", () => {
40
+ expect(isOwned(line({
41
+ pid: 660,
42
+ tag: "ActivityManager",
43
+ level: "error",
44
+ message: "ANR in com.rndebuggertestapp",
45
+ }), APP)).toEqual({ owned: true, reason: "verdict" });
46
+ });
47
+ it("rejects MMKV lines that contain the package as a FILESYSTEM PATH", () => {
48
+ expect(isOwned(line({
49
+ pid: 998,
50
+ tag: "MMKV",
51
+ message: "<MemoryFile.cpp:103::open> open fd[138] /data/data/com.rndebuggertestapp/files/mmkv",
52
+ }), { ...APP, pid: undefined })).toEqual({ owned: false });
53
+ });
54
+ it("rejects nativeloader apk paths from a foreign pid", () => {
55
+ expect(isOwned(line({
56
+ pid: 777,
57
+ tag: "nativeloader",
58
+ message: "Load /data/app/~~s-V8/com.rndebuggertestapp-Ht1RP33/base.apk!/lib/arm64-v8a/librnscreens.so: ok",
59
+ }), { ...APP, pid: undefined })).toEqual({ owned: false });
60
+ });
61
+ it("rejects ActivityThread lines emitted by OTHER apps' pids", () => {
62
+ expect(isOwned(line({
63
+ pid: 21908,
64
+ tag: "ActivityThread",
65
+ message: "Package [com.rndebuggertestapp] reported as REPLACED, but missing application info.",
66
+ }), { ...APP, pid: undefined })).toEqual({ owned: false });
67
+ });
68
+ it("rejects an allowlisted tag that names a DIFFERENT package", () => {
69
+ expect(isOwned(line({
70
+ pid: 660,
71
+ tag: "ActivityManager",
72
+ message: "ANR in com.google.android.apps.messaging",
73
+ }), APP)).toEqual({ owned: false });
74
+ });
75
+ it("rejects a sibling package that merely EXTENDS the app id", () => {
76
+ // Debug/release variants differing by applicationIdSuffix are normal.
77
+ expect(isOwned(line({
78
+ pid: 660,
79
+ tag: "ActivityManager",
80
+ level: "error",
81
+ message: "ANR in com.rndebuggertestapp.debug",
82
+ }), APP)).toEqual({ owned: false });
83
+ });
84
+ it("rejects a parent package when the app id is the longer one", () => {
85
+ expect(isOwned(line({
86
+ pid: 660,
87
+ tag: "ActivityManager",
88
+ level: "error",
89
+ message: "ANR in com.rndebuggertestapp",
90
+ }), { ...APP, appId: "com.rndebuggertestapp.debug" })).toEqual({ owned: false });
91
+ });
92
+ it("still owns an exact package match at end of message", () => {
93
+ expect(isOwned(line({
94
+ pid: 660,
95
+ tag: "ActivityManager",
96
+ level: "error",
97
+ message: "ANR in com.rndebuggertestapp",
98
+ }), APP)).toEqual({ owned: true, reason: "verdict" });
99
+ });
100
+ it("rejects a ReactNativeJS line from the app's own LIVE PID", () => {
101
+ // React Native mirrors console.* into logcat under this tag. It is
102
+ // already in the CDP console buffer, so owning it here would
103
+ // double-report under source:"all" — the pid match alone (rule 2)
104
+ // would otherwise happily claim it.
105
+ expect(isOwned(line({
106
+ pid: 23325,
107
+ tag: "ReactNativeJS",
108
+ message: "[TapTargetsScreen] Tapped: submit-btn",
109
+ }), APP)).toEqual({ owned: false });
110
+ });
111
+ it("still owns a non-mirrored tag from that same live pid", () => {
112
+ // Confirms the denylist targets the TAG, not the pid generally —
113
+ // ordinary native output from the same process is unaffected.
114
+ expect(isOwned(line({ pid: 23325, tag: "ReactNative" }), APP))
115
+ .toEqual({ owned: true, reason: "pid" });
116
+ });
117
+ });
118
+ //# sourceMappingURL=logOwnership.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logOwnership.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/logOwnership.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=logRelevance.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logRelevance.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/logRelevance.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,30 @@
1
+ import { describe, it, expect } from "@jest/globals";
2
+ import { isRelevant } from "../../core/logRelevance.js";
3
+ describe("isRelevant", () => {
4
+ it("drops owned-but-noisy debug messages", () => {
5
+ // nativeloader / jni_lib_merge / SoLoader: 152 of the app's own 266
6
+ // lines on a live device. Owned, and still pure noise.
7
+ expect(isRelevant({ level: "debug", kind: "message" }, { minLevel: "warn" })).toBe(false);
8
+ });
9
+ it("keeps warnings at the default floor", () => {
10
+ expect(isRelevant({ level: "warn", kind: "message" }, { minLevel: "warn" })).toBe(true);
11
+ });
12
+ it("keeps a crash even below the floor", () => {
13
+ // The whole point of the feature: a level threshold must never be able
14
+ // to suppress a crash.
15
+ expect(isRelevant({ level: "debug", kind: "crash" }, { minLevel: "fatal" })).toBe(true);
16
+ });
17
+ it("keeps an ANR even below the floor", () => {
18
+ expect(isRelevant({ level: "info", kind: "anr" }, { minLevel: "error" })).toBe(true);
19
+ });
20
+ it("opens the floodgates at minLevel debug", () => {
21
+ expect(isRelevant({ level: "debug", kind: "message" }, { minLevel: "debug" })).toBe(true);
22
+ });
23
+ it("does not exempt other kinds from the floor", () => {
24
+ // ALWAYS is the only thing separating "exempt" from "filtered", so pin
25
+ // the kinds that must NOT be exempt.
26
+ expect(isRelevant({ level: "debug", kind: "exception" }, { minLevel: "warn" })).toBe(false);
27
+ expect(isRelevant({ level: "debug", kind: "lifecycle" }, { minLevel: "warn" })).toBe(false);
28
+ });
29
+ });
30
+ //# sourceMappingURL=logRelevance.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logRelevance.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/logRelevance.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAExD,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IACxB,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC5C,oEAAoE;QACpE,uDAAuD;QACvD,MAAM,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC1C,uEAAuE;QACvE,uBAAuB;QACvB,MAAM,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QACzC,MAAM,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QAClD,uEAAuE;QACvE,qCAAqC;QACrC,MAAM,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5F,MAAM,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChG,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=logSourceAndroid.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logSourceAndroid.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/logSourceAndroid.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,61 @@
1
+ import { describe, it, expect } from "@jest/globals";
2
+ import { buildLogcatArgs, parseLogcatEpoch } from "../../core/logSourceAndroid.js";
3
+ describe("buildLogcatArgs", () => {
4
+ it("always reads the crash buffer alongside main", () => {
5
+ // -b crash is tiny (121 lines) and near-100% signal; it is also the
6
+ // only place a tombstone lands.
7
+ expect(buildLogcatArgs({ serial: "emulator-5554" })).toContain("-b crash,main");
8
+ });
9
+ it("uses epoch, not year, for timestamps", () => {
10
+ // -v year prints device-local wall time with NO utc offset, so a device
11
+ // in another timezone silently shifts every entry.
12
+ const args = buildLogcatArgs({ serial: "emulator-5554" });
13
+ expect(args).toContain("-v epoch");
14
+ expect(args).not.toContain("-v year");
15
+ });
16
+ it("passes the device serial", () => {
17
+ expect(buildLogcatArgs({ serial: "emulator-5554" })).toContain("-s emulator-5554");
18
+ });
19
+ it("windows on the watermark when given", () => {
20
+ const args = buildLogcatArgs({ sinceTs: new Date("2026-07-29T22:12:00.000Z") });
21
+ expect(args).toMatch(/-T ['"]?1785[0-9]{6}\.000/);
22
+ });
23
+ it("omits --pid when the app is dead", () => {
24
+ expect(buildLogcatArgs({})).not.toContain("--pid");
25
+ });
26
+ });
27
+ describe("parseLogcatEpoch", () => {
28
+ const SAMPLE = [
29
+ "--------- beginning of main",
30
+ " 1785352265.203 1210 13886 I NearbyMediums: Wifi changed new SSID",
31
+ " 1785352265.015 22617 22617 F DEBUG : Cmdline: com.rndebuggertestapp",
32
+ " 1785352265.015 22617 22617 F DEBUG : pid: 17782, tid: 17832, name: x >>> com.rndebuggertestapp <<<",
33
+ " 1785352266.100 660 813 E ActivityManager: ANR in com.rndebuggertestapp",
34
+ ].join("\n");
35
+ it("skips banner lines", () => {
36
+ expect(parseLogcatEpoch(SAMPLE).some((l) => l.message.includes("beginning of"))).toBe(false);
37
+ });
38
+ it("parses pid, tid, level, tag and message", () => {
39
+ const first = parseLogcatEpoch(SAMPLE)[0];
40
+ expect(first.pid).toBe(1210);
41
+ expect(first.tid).toBe(13886);
42
+ expect(first.level).toBe("info");
43
+ expect(first.tag).toBe("NearbyMediums");
44
+ expect(first.message).toBe("Wifi changed new SSID");
45
+ });
46
+ it("maps F to fatal and E to error", () => {
47
+ const lines = parseLogcatEpoch(SAMPLE);
48
+ expect(lines[1].level).toBe("fatal");
49
+ expect(lines[3].level).toBe("error");
50
+ });
51
+ it("extracts the declared subject from Cmdline:", () => {
52
+ expect(parseLogcatEpoch(SAMPLE)[1].subject).toBe("com.rndebuggertestapp");
53
+ });
54
+ it("extracts the declared subject from >>> pkg <<<", () => {
55
+ expect(parseLogcatEpoch(SAMPLE)[2].subject).toBe("com.rndebuggertestapp");
56
+ });
57
+ it("converts epoch seconds to an absolute Date", () => {
58
+ expect(parseLogcatEpoch(SAMPLE)[0].ts.getTime()).toBe(1785352265203);
59
+ });
60
+ });
61
+ //# sourceMappingURL=logSourceAndroid.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logSourceAndroid.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/logSourceAndroid.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=logSourceIos.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logSourceIos.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/logSourceIos.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,64 @@
1
+ import { describe, it, expect } from "@jest/globals";
2
+ import { buildLogShowCommand, parseLogShowNdjson } from "../../core/logSourceIos.js";
3
+ const UDID = "F93612A3-0042-4BDC-855F-8CAB1BDD76C6";
4
+ describe("buildLogShowCommand", () => {
5
+ it("spawns against the given simulator", () => {
6
+ expect(buildLogShowCommand({ udid: UDID })).toContain(`simctl spawn ${UDID}`);
7
+ });
8
+ it("requests ndjson", () => {
9
+ expect(buildLogShowCommand({ udid: UDID })).toContain("--style ndjson");
10
+ });
11
+ it("pushes the process filter into the predicate", () => {
12
+ // 30m app-scoped is 42KB; unfiltered is orders of magnitude more.
13
+ const cmd = buildLogShowCommand({ udid: UDID, processName: "RnDebuggerTestApp" });
14
+ expect(cmd).toContain(`process == "RnDebuggerTestApp"`);
15
+ });
16
+ it("emits --start in device-local time, not UTC", () => {
17
+ // log show parses a bare --start as LOCAL and rejects an explicit
18
+ // offset, so a UTC stamp shifts the window by the host's offset —
19
+ // over-fetching east of UTC, silently missing crashes west of it.
20
+ const when = new Date(2026, 6, 29, 22, 15, 30);
21
+ expect(buildLogShowCommand({ udid: "U", sinceTs: when }))
22
+ .toContain("--start '2026-07-29 22:15:30'");
23
+ });
24
+ });
25
+ describe("parseLogShowNdjson", () => {
26
+ const SAMPLE = [
27
+ JSON.stringify({
28
+ timestamp: "2026-07-29 21:34:54.667179+0300",
29
+ messageType: "Error",
30
+ processID: 19743,
31
+ threadID: 1234,
32
+ subsystem: "com.apple.network",
33
+ category: "connection",
34
+ eventMessage: "nw_socket_handle_socket_event [C1.1.1:2] Socket SO_ERROR [61: Connection refused]",
35
+ }),
36
+ JSON.stringify({
37
+ timestamp: "2026-07-29 21:34:47.594000+0300",
38
+ messageType: "Default",
39
+ processID: 19743,
40
+ subsystem: "",
41
+ category: "",
42
+ eventMessage: "_setUpFeatureFlags called with release level 2",
43
+ }),
44
+ JSON.stringify({ count: 888, finished: 1 }),
45
+ ].join("\n");
46
+ it("skips the trailing summary object", () => {
47
+ expect(parseLogShowNdjson(SAMPLE)).toHaveLength(2);
48
+ });
49
+ it("maps messageType onto levels", () => {
50
+ expect(parseLogShowNdjson(SAMPLE)[0].level).toBe("error");
51
+ expect(parseLogShowNdjson(SAMPLE)[1].level).toBe("log");
52
+ });
53
+ it("builds the tag from subsystem and category", () => {
54
+ expect(parseLogShowNdjson(SAMPLE)[0].tag).toBe("com.apple.network:connection");
55
+ });
56
+ it("parses the offset-aware timestamp", () => {
57
+ // 21:34:54.667 +0300 == 18:34:54.667 UTC
58
+ expect(parseLogShowNdjson(SAMPLE)[0].ts.toISOString()).toBe("2026-07-29T18:34:54.667Z");
59
+ });
60
+ it("tolerates malformed lines rather than throwing", () => {
61
+ expect(parseLogShowNdjson("not json\n" + SAMPLE)).toHaveLength(2);
62
+ });
63
+ });
64
+ //# sourceMappingURL=logSourceIos.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logSourceIos.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/logSourceIos.test.ts"],"names":[],"mappings":"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"}
@@ -87,4 +87,27 @@ describe("mapConsoleType", () => {
87
87
  it("maps debug to debug", () => expect(mapConsoleType("debug")).toBe("debug"));
88
88
  it("maps unknown to log", () => expect(mapConsoleType("trace")).toBe("log"));
89
89
  });
90
+ describe("LogBuffer seq assignment", () => {
91
+ it("assigns a monotonic seq to every entry", () => {
92
+ const buffer = new LogBuffer(10);
93
+ buffer.add(makeLog("first"));
94
+ buffer.add(makeLog("second"));
95
+ const [a, b] = buffer.getAll();
96
+ expect(typeof a.seq).toBe("number");
97
+ expect(b.seq).toBeGreaterThan(a.seq);
98
+ });
99
+ it("keeps seq unique across separate buffers", () => {
100
+ // Two devices, two buffers, one id space — ids must never collide.
101
+ const one = new LogBuffer(10);
102
+ const two = new LogBuffer(10);
103
+ one.add(makeLog("device-a"));
104
+ two.add(makeLog("device-b"));
105
+ expect(one.getAll()[0].seq).not.toBe(two.getAll()[0].seq);
106
+ });
107
+ it("accepts the fatal level", () => {
108
+ const buffer = new LogBuffer(10);
109
+ buffer.add(makeLog("native crash", "fatal"));
110
+ expect(buffer.getAll()[0].level).toBe("fatal");
111
+ });
112
+ });
90
113
  //# sourceMappingURL=logs.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"logs.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/logs.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"logs.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/logs.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=nativeLogs.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nativeLogs.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/nativeLogs.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,230 @@
1
+ import { describe, it, expect, jest, beforeEach } from "@jest/globals";
2
+ const listDevicesMock = jest.fn();
3
+ const recordDeviceMock = jest.fn();
4
+ jest.unstable_mockModule("../../core/projectMemory.js", () => ({
5
+ listDevices: listDevicesMock,
6
+ recordDevice: recordDeviceMock,
7
+ recordScreenMetrics: jest.fn(),
8
+ }));
9
+ const connectedAppsMock = new Map();
10
+ jest.unstable_mockModule("../../core/state.js", () => ({
11
+ connectedApps: connectedAppsMock,
12
+ }));
13
+ const listAllDevicesMock = jest.fn();
14
+ jest.unstable_mockModule("../../core/deviceDiscovery.js", () => ({
15
+ listAllDevices: listAllDevicesMock,
16
+ }));
17
+ const execAsyncMock = jest.fn();
18
+ jest.unstable_mockModule("../../core/exec.js", () => ({
19
+ execAsync: execAsyncMock,
20
+ // logSourceAndroid.js / logSourceIos.js import this too — unused by these
21
+ // tests (fetchForTarget is never exercised here) but must exist so the
22
+ // module graph resolves.
23
+ withCancelableTimeout: jest.fn(),
24
+ }));
25
+ const { runNativePipeline, identityFromMemory, resolveLogTargets } = await import("../../core/nativeLogs.js");
26
+ const { __resetNativeLogBuffers } = await import("../../core/logEvents.js");
27
+ function emptyDiscovery() {
28
+ return {
29
+ ios: { available: true, simulators: [] },
30
+ android: { available: true, emulators: [], physical: [] },
31
+ summary: { booted: 0, total: 0 },
32
+ };
33
+ }
34
+ const APP = {
35
+ deviceKey: "emulator-5554",
36
+ platform: "android",
37
+ appId: "com.rndebuggertestapp",
38
+ pid: 23325,
39
+ };
40
+ let clock = 0;
41
+ function line(over) {
42
+ clock += 1;
43
+ return {
44
+ ts: new Date(Date.UTC(2026, 6, 29, 22, 11, 5, clock)),
45
+ level: "info", pid: 23325, tid: 23325, tag: "X", message: "", raw: "x",
46
+ ...over,
47
+ };
48
+ }
49
+ /** Minimal DeviceMemoryEntry builder — only the fields the lookup reads matter. */
50
+ function memoryRow(over) {
51
+ return {
52
+ identifier: "emulator-5554",
53
+ name: "Pixel",
54
+ platform: "android",
55
+ firstSeenAt: 0,
56
+ lastUsedAt: 0,
57
+ useCount: 1,
58
+ ...over,
59
+ };
60
+ }
61
+ describe("runNativePipeline", () => {
62
+ beforeEach(() => {
63
+ __resetNativeLogBuffers();
64
+ listDevicesMock.mockReset();
65
+ listDevicesMock.mockReturnValue([]);
66
+ });
67
+ it("drops foreign lines, noise, and keeps the crash", () => {
68
+ const lines = [
69
+ line({ pid: 998, tag: "MMKV", message: "open /data/data/com.rndebuggertestapp/files/mmkv" }),
70
+ line({ pid: 23325, tag: "nativeloader", level: "debug", message: "Load librnscreens.so: ok" }),
71
+ line({ pid: 22617, tid: 22617, tag: "DEBUG", level: "fatal", subject: "com.rndebuggertestapp", message: "Cmdline: com.rndebuggertestapp" }),
72
+ line({ pid: 22617, tid: 22617, tag: "DEBUG", level: "fatal", message: "signal 6 (SIGABRT), code -1" }),
73
+ ];
74
+ const { events } = runNativePipeline(lines, APP, "Pixel", { minLevel: "warn" });
75
+ expect(events).toHaveLength(1);
76
+ expect(events[0].kind).toBe("crash");
77
+ expect(events[0].id).toMatch(/^n\d+$/);
78
+ });
79
+ it("is idempotent across an inclusive refetch", () => {
80
+ const lines = [
81
+ line({ pid: 22617, tid: 22617, tag: "DEBUG", level: "fatal", subject: "com.rndebuggertestapp", message: "Cmdline: com.rndebuggertestapp" }),
82
+ ];
83
+ expect(runNativePipeline(lines, APP, "Pixel", { minLevel: "warn" }).events).toHaveLength(1);
84
+ expect(runNativePipeline(lines, APP, "Pixel", { minLevel: "warn" }).events).toHaveLength(0);
85
+ });
86
+ it("keeps two devices sharing one appId separate", () => {
87
+ const other = { ...APP, deviceKey: "emulator-5556" };
88
+ const mk = () => [line({ pid: 22617, tid: 22617, tag: "DEBUG", level: "fatal", subject: "com.rndebuggertestapp", message: "Cmdline: com.rndebuggertestapp" })];
89
+ const a = runNativePipeline(mk(), APP, "Pixel A", { minLevel: "warn" });
90
+ const b = runNativePipeline(mk(), other, "Pixel B", { minLevel: "warn" });
91
+ expect(a.events).toHaveLength(1);
92
+ expect(b.events).toHaveLength(1); // NOT deduped against device A
93
+ expect(a.events[0].id).not.toBe(b.events[0].id);
94
+ });
95
+ });
96
+ describe("identityFromMemory", () => {
97
+ beforeEach(() => {
98
+ listDevicesMock.mockReset();
99
+ });
100
+ it("finds a remembered appId keyed by device NAME, not just serial", () => {
101
+ // projectMemory can hold two rows for one physical device: one keyed by
102
+ // the adb serial (from one call path) with no appId, and one keyed by
103
+ // the RN deviceName (from another) that carries it. Looking up by
104
+ // serial alone made this fallback dead on Android.
105
+ listDevicesMock.mockReturnValue([
106
+ memoryRow({ identifier: "emulator-5554", appId: undefined }),
107
+ memoryRow({
108
+ identifier: "sdk_gphone16k_arm64 - 16 - API 36",
109
+ name: "sdk_gphone16k_arm64 - 16 - API 36",
110
+ appId: "com.gifted.production",
111
+ }),
112
+ ]);
113
+ const identity = identityFromMemory("emulator-5554", "android", "sdk_gphone16k_arm64 - 16 - API 36");
114
+ expect(identity).toEqual({
115
+ deviceKey: "emulator-5554",
116
+ platform: "android",
117
+ appId: "com.gifted.production",
118
+ });
119
+ });
120
+ it("ignores a matching row whose appId is undefined", () => {
121
+ // The serial-keyed row exists but has no appId, and no deviceName is
122
+ // supplied to fall back to — the empty row must not produce a false
123
+ // "found" result.
124
+ listDevicesMock.mockReturnValue([
125
+ memoryRow({ identifier: "emulator-5554", appId: undefined }),
126
+ ]);
127
+ expect(identityFromMemory("emulator-5554", "android")).toBeUndefined();
128
+ });
129
+ });
130
+ describe("resolveLogTargets", () => {
131
+ beforeEach(() => {
132
+ connectedAppsMock.clear();
133
+ listAllDevicesMock.mockReset();
134
+ recordDeviceMock.mockReset();
135
+ listDevicesMock.mockReset();
136
+ listDevicesMock.mockReturnValue([]);
137
+ execAsyncMock.mockReset();
138
+ });
139
+ it("records live identity under the device key so it survives a later crash", async () => {
140
+ // projectMemory's appId row is keyed by the RN deviceName on Android,
141
+ // which nothing links back to the adb serial — so identity must be
142
+ // written under the buffer key (the serial) while the app is still
143
+ // alive, or the post-crash lookup in identityFromMemory has nothing
144
+ // to find.
145
+ const app = {
146
+ deviceInfo: {
147
+ deviceName: "sdk_gphone16k_arm64 - 16 - API 36",
148
+ appId: "com.gifted.production",
149
+ },
150
+ platform: "android",
151
+ adbSerial: "emulator-5554",
152
+ };
153
+ connectedAppsMock.set("emulator-5554", app);
154
+ listAllDevicesMock.mockResolvedValue({
155
+ ...emptyDiscovery(),
156
+ android: {
157
+ available: true,
158
+ // Discovery's own name for the row is the AVD name — a third,
159
+ // unrelated value that also cannot bridge serial -> RN name.
160
+ emulators: [{ name: "Pixel_9_-_16kb", serial: "emulator-5554", state: "running" }],
161
+ physical: [],
162
+ },
163
+ });
164
+ await resolveLogTargets();
165
+ expect(recordDeviceMock).toHaveBeenCalledWith({
166
+ identifier: "emulator-5554",
167
+ name: "sdk_gphone16k_arm64 - 16 - API 36",
168
+ platform: "android",
169
+ appId: "com.gifted.production",
170
+ });
171
+ });
172
+ it("matches an Android app with a null adbSerial via the model prefix", async () => {
173
+ // ConnectedApp.adbSerial is frequently null (only set when
174
+ // getAdbIdForAvd happens to match at connect time), so the
175
+ // serial-keyed lookup in `connected` misses this app entirely. The
176
+ // model-prefix fallback is what recovers live identity here.
177
+ const app = {
178
+ deviceInfo: {
179
+ deviceName: "sdk_gphone16k_arm64 - 16 - API 36",
180
+ appId: "com.rndebuggertestapp",
181
+ },
182
+ platform: "android",
183
+ adbSerial: null,
184
+ };
185
+ connectedAppsMock.set("some-registry-key", app);
186
+ execAsyncMock.mockResolvedValue({ stdout: "sdk_gphone16k_arm64\n", stderr: "" });
187
+ listAllDevicesMock.mockResolvedValue({
188
+ ...emptyDiscovery(),
189
+ android: {
190
+ available: true,
191
+ emulators: [{ name: "Pixel_9_-_16kb", serial: "emulator-5554", state: "running" }],
192
+ physical: [],
193
+ },
194
+ });
195
+ const targets = await resolveLogTargets();
196
+ expect(execAsyncMock).toHaveBeenCalledWith("adb -s emulator-5554 shell getprop ro.product.model");
197
+ expect(targets).toHaveLength(1);
198
+ expect(targets[0].identitySource).toBe("live");
199
+ expect(targets[0].identity).toEqual({
200
+ deviceKey: "emulator-5554",
201
+ platform: "android",
202
+ appId: "com.rndebuggertestapp",
203
+ });
204
+ });
205
+ it("yields no live identity when the model does not match any connected app", async () => {
206
+ const app = {
207
+ deviceInfo: {
208
+ deviceName: "some_other_device - 14 - API 34",
209
+ appId: "com.someother.app",
210
+ },
211
+ platform: "android",
212
+ adbSerial: null,
213
+ };
214
+ connectedAppsMock.set("some-registry-key", app);
215
+ execAsyncMock.mockResolvedValue({ stdout: "sdk_gphone16k_arm64\n", stderr: "" });
216
+ listAllDevicesMock.mockResolvedValue({
217
+ ...emptyDiscovery(),
218
+ android: {
219
+ available: true,
220
+ emulators: [{ name: "Pixel_9_-_16kb", serial: "emulator-5554", state: "running" }],
221
+ physical: [],
222
+ },
223
+ });
224
+ const targets = await resolveLogTargets();
225
+ expect(targets).toHaveLength(1);
226
+ expect(targets[0].identitySource).not.toBe("live");
227
+ expect(targets[0].identity).toBeUndefined();
228
+ });
229
+ });
230
+ //# sourceMappingURL=nativeLogs.test.js.map