@reticlehq/browser 2.0.1 → 2.2.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 (179) hide show
  1. package/NOTICE +5 -0
  2. package/dist/actions/actions-dom.d.ts.map +1 -1
  3. package/dist/actions/actions-dom.js +3 -20
  4. package/dist/actions/actions-dom.js.map +1 -1
  5. package/dist/actions/actions.d.ts +1 -1
  6. package/dist/actions/actions.d.ts.map +1 -1
  7. package/dist/actions/actions.js +37 -19
  8. package/dist/actions/actions.js.map +1 -1
  9. package/dist/commands/commands.d.ts +2 -0
  10. package/dist/commands/commands.d.ts.map +1 -1
  11. package/dist/commands/commands.js +30 -31
  12. package/dist/commands/commands.js.map +1 -1
  13. package/dist/dom/a11y.d.ts +17 -6
  14. package/dist/dom/a11y.d.ts.map +1 -1
  15. package/dist/dom/a11y.js +68 -32
  16. package/dist/dom/a11y.js.map +1 -1
  17. package/dist/dom/auto-anchor.d.ts +10 -10
  18. package/dist/dom/auto-anchor.js +10 -10
  19. package/dist/dom/blind-spots.d.ts +14 -0
  20. package/dist/dom/blind-spots.d.ts.map +1 -0
  21. package/dist/dom/blind-spots.js +30 -0
  22. package/dist/dom/blind-spots.js.map +1 -0
  23. package/dist/dom/chart.d.ts +93 -0
  24. package/dist/dom/chart.d.ts.map +1 -0
  25. package/dist/dom/chart.js +119 -0
  26. package/dist/dom/chart.js.map +1 -0
  27. package/dist/dom/dom-ignore.d.ts +2 -0
  28. package/dist/dom/dom-ignore.d.ts.map +1 -1
  29. package/dist/dom/dom-ignore.js +17 -2
  30. package/dist/dom/dom-ignore.js.map +1 -1
  31. package/dist/dom/occlusion.d.ts +9 -0
  32. package/dist/dom/occlusion.d.ts.map +1 -0
  33. package/dist/dom/occlusion.js +21 -0
  34. package/dist/dom/occlusion.js.map +1 -0
  35. package/dist/dom/query.d.ts +17 -4
  36. package/dist/dom/query.d.ts.map +1 -1
  37. package/dist/dom/query.js +185 -30
  38. package/dist/dom/query.js.map +1 -1
  39. package/dist/dom/refs.d.ts +26 -3
  40. package/dist/dom/refs.d.ts.map +1 -1
  41. package/dist/dom/refs.js +79 -4
  42. package/dist/dom/refs.js.map +1 -1
  43. package/dist/dom/snapshot.d.ts +7 -1
  44. package/dist/dom/snapshot.d.ts.map +1 -1
  45. package/dist/dom/snapshot.js +43 -16
  46. package/dist/dom/snapshot.js.map +1 -1
  47. package/dist/dom/source.d.ts +40 -0
  48. package/dist/dom/source.d.ts.map +1 -0
  49. package/dist/dom/source.js +59 -0
  50. package/dist/dom/source.js.map +1 -0
  51. package/dist/dom/theme.js +2 -2
  52. package/dist/dom/theme.js.map +1 -1
  53. package/dist/index.d.ts +6 -2
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +9 -1
  56. package/dist/index.js.map +1 -1
  57. package/dist/observers/animation.d.ts +1 -1
  58. package/dist/observers/animation.d.ts.map +1 -1
  59. package/dist/observers/animation.js +1 -1
  60. package/dist/observers/animation.js.map +1 -1
  61. package/dist/observers/blind-spots.d.ts +19 -0
  62. package/dist/observers/blind-spots.d.ts.map +1 -0
  63. package/dist/observers/blind-spots.js +89 -0
  64. package/dist/observers/blind-spots.js.map +1 -0
  65. package/dist/observers/console.d.ts.map +1 -1
  66. package/dist/observers/console.js +39 -6
  67. package/dist/observers/console.js.map +1 -1
  68. package/dist/observers/dom.d.ts +1 -1
  69. package/dist/observers/dom.d.ts.map +1 -1
  70. package/dist/observers/dom.js +69 -10
  71. package/dist/observers/dom.js.map +1 -1
  72. package/dist/observers/focus.d.ts +10 -0
  73. package/dist/observers/focus.d.ts.map +1 -0
  74. package/dist/observers/focus.js +49 -0
  75. package/dist/observers/focus.js.map +1 -0
  76. package/dist/observers/network-body.d.ts +19 -0
  77. package/dist/observers/network-body.d.ts.map +1 -0
  78. package/dist/observers/network-body.js +143 -0
  79. package/dist/observers/network-body.js.map +1 -0
  80. package/dist/observers/network-redact.d.ts +8 -0
  81. package/dist/observers/network-redact.d.ts.map +1 -0
  82. package/dist/observers/network-redact.js +66 -0
  83. package/dist/observers/network-redact.js.map +1 -0
  84. package/dist/observers/network.d.ts +19 -7
  85. package/dist/observers/network.d.ts.map +1 -1
  86. package/dist/observers/network.js +439 -53
  87. package/dist/observers/network.js.map +1 -1
  88. package/dist/observers/perf.d.ts +13 -0
  89. package/dist/observers/perf.d.ts.map +1 -0
  90. package/dist/observers/perf.js +62 -0
  91. package/dist/observers/perf.js.map +1 -0
  92. package/dist/observers/route.d.ts.map +1 -1
  93. package/dist/observers/route.js +19 -10
  94. package/dist/observers/route.js.map +1 -1
  95. package/dist/observers/scroll.d.ts +1 -1
  96. package/dist/observers/scroll.d.ts.map +1 -1
  97. package/dist/observers/scroll.js +36 -9
  98. package/dist/observers/scroll.js.map +1 -1
  99. package/dist/observers/state.d.ts +20 -0
  100. package/dist/observers/state.d.ts.map +1 -0
  101. package/dist/observers/state.js +87 -0
  102. package/dist/observers/state.js.map +1 -0
  103. package/dist/observers/storage.d.ts +23 -0
  104. package/dist/observers/storage.d.ts.map +1 -0
  105. package/dist/observers/storage.js +177 -0
  106. package/dist/observers/storage.js.map +1 -0
  107. package/dist/observers/types.d.ts +15 -0
  108. package/dist/observers/types.d.ts.map +1 -1
  109. package/dist/observers/types.js +29 -1
  110. package/dist/observers/types.js.map +1 -1
  111. package/dist/patching/capture-method.d.ts +27 -0
  112. package/dist/patching/capture-method.d.ts.map +1 -0
  113. package/dist/patching/capture-method.js +37 -0
  114. package/dist/patching/capture-method.js.map +1 -0
  115. package/dist/presenter/presenter-config.d.ts +3 -3
  116. package/dist/presenter/presenter-config.d.ts.map +1 -1
  117. package/dist/presenter/presenter-config.js +3 -3
  118. package/dist/presenter/presenter-config.js.map +1 -1
  119. package/dist/presenter/presenter-controls.d.ts +1 -1
  120. package/dist/presenter/presenter-controls.d.ts.map +1 -1
  121. package/dist/presenter/presenter-controls.js +3 -3
  122. package/dist/presenter/presenter-controls.js.map +1 -1
  123. package/dist/presenter/presenter-glow.d.ts +1 -1
  124. package/dist/presenter/presenter-glow.js +1 -1
  125. package/dist/presenter/presenter-styles.d.ts +1 -1
  126. package/dist/presenter/presenter-styles.d.ts.map +1 -1
  127. package/dist/presenter/presenter-styles.js +12 -3
  128. package/dist/presenter/presenter-styles.js.map +1 -1
  129. package/dist/presenter/presenter-test-helpers.d.ts +16 -0
  130. package/dist/presenter/presenter-test-helpers.d.ts.map +1 -0
  131. package/dist/presenter/presenter-test-helpers.js +42 -0
  132. package/dist/presenter/presenter-test-helpers.js.map +1 -0
  133. package/dist/presenter/presenter.d.ts +4 -6
  134. package/dist/presenter/presenter.d.ts.map +1 -1
  135. package/dist/presenter/presenter.js +5 -9
  136. package/dist/presenter/presenter.js.map +1 -1
  137. package/dist/recorder/recorder.d.ts +8 -8
  138. package/dist/recorder/recorder.d.ts.map +1 -1
  139. package/dist/recorder/recorder.js +22 -9
  140. package/dist/recorder/recorder.js.map +1 -1
  141. package/dist/registry/capabilities.d.ts +2 -2
  142. package/dist/registry/capabilities.d.ts.map +1 -1
  143. package/dist/registry/capabilities.js +1 -1
  144. package/dist/registry/capabilities.js.map +1 -1
  145. package/dist/registry/domains.d.ts +1 -1
  146. package/dist/registry/domains.js +1 -1
  147. package/dist/registry/emitter.d.ts +2 -2
  148. package/dist/registry/emitter.js +2 -2
  149. package/dist/registry/store-adapters.d.ts +128 -0
  150. package/dist/registry/store-adapters.d.ts.map +1 -0
  151. package/dist/registry/store-adapters.js +135 -0
  152. package/dist/registry/store-adapters.js.map +1 -0
  153. package/dist/registry/stores.d.ts +45 -3
  154. package/dist/registry/stores.d.ts.map +1 -1
  155. package/dist/registry/stores.js +121 -8
  156. package/dist/registry/stores.js.map +1 -1
  157. package/dist/reticle.d.ts +28 -4
  158. package/dist/reticle.d.ts.map +1 -1
  159. package/dist/reticle.js +83 -15
  160. package/dist/reticle.js.map +1 -1
  161. package/dist/review/annotator.d.ts.map +1 -1
  162. package/dist/review/annotator.js +4 -2
  163. package/dist/review/annotator.js.map +1 -1
  164. package/dist/review/mark-anchor.d.ts.map +1 -1
  165. package/dist/review/mark-anchor.js +1 -21
  166. package/dist/review/mark-anchor.js.map +1 -1
  167. package/dist/security/serialization.d.ts +29 -1
  168. package/dist/security/serialization.d.ts.map +1 -1
  169. package/dist/security/serialization.js +172 -20
  170. package/dist/security/serialization.js.map +1 -1
  171. package/dist/timers/clock.d.ts +13 -0
  172. package/dist/timers/clock.d.ts.map +1 -1
  173. package/dist/timers/clock.js +76 -6
  174. package/dist/timers/clock.js.map +1 -1
  175. package/dist/transport/transport.d.ts +1 -1
  176. package/dist/transport/transport.d.ts.map +1 -1
  177. package/dist/transport/transport.js +49 -8
  178. package/dist/transport/transport.js.map +1 -1
  179. package/package.json +7 -3
@@ -1,29 +1,80 @@
1
- import { EventType, REDACTED_VALUE } from '@reticlehq/core';
2
- import { isSensitiveKey } from '../security/serialization.js';
1
+ import { BlindSpotKind, EventType, RETICLE_WS_PATH, StreamTransport, StreamDirection, } from '@reticlehq/core';
2
+ import { captureMethod } from '../patching/capture-method.js';
3
+ import { isCapturableType, projectBody, withBodyDeadline } from './network-body.js';
4
+ import { redactUrl } from './network-redact.js';
5
+ // Redaction moved to its own cohesive module (network.ts is at its line cap); re-exported so callers
6
+ // and the existing test suite keep importing it from here.
7
+ export { redactUrl };
8
+ /** The byte size of a binary frame (ArrayBuffer / Blob / typed-array view), or undefined if unknown. */
9
+ function binaryFrameBytes(data) {
10
+ if (data instanceof ArrayBuffer)
11
+ return data.byteLength;
12
+ if (typeof Blob !== 'undefined' && data instanceof Blob)
13
+ return data.size;
14
+ if (ArrayBuffer.isView(data))
15
+ return data.byteLength;
16
+ return undefined;
17
+ }
18
+ /** Project one SSE/WebSocket frame: byte size + shape; the (capped, redacted) payload only when body
19
+ * capture is on and it is a string frame. Binary frames report their byte size, not just a bare type. */
20
+ function frameFields(data, captureBodies) {
21
+ if (typeof data !== 'string') {
22
+ const bytes = binaryFrameBytes(data);
23
+ return bytes === undefined
24
+ ? { frameType: typeof data }
25
+ : { frameType: 'binary', frameBytes: bytes };
26
+ }
27
+ const out = { frameBytes: data.length };
28
+ if (captureBodies) {
29
+ const { body, truncated } = projectBody(data, 'application/json');
30
+ out['frame'] = body;
31
+ if (truncated)
32
+ out['frameTruncated'] = true;
33
+ }
34
+ return out;
35
+ }
3
36
  /**
4
- * Redact credential-bearing query params (`?access_token=…`, signed-URL keys, magic-link tokens) so
5
- * they don't leak into the agent transcript / flow / run artifacts. Only the query string is rewritten
6
- * — the path (relative or absolute) and any hash are preserved — and only when something actually
7
- * matched, so non-sensitive URLs pass through byte-for-byte. Uses the shared `isSensitiveKey` regex.
37
+ * The request body for the transcript. Plain strings and URLSearchParams are captured (redacted, capped);
38
+ * FormData/Blob/ArrayBuffer/stream aren't text so they get a `requestBodyType` marker (the agent still
39
+ * learns a body existed) rather than being silently dropped. Shared by the fetch and XHR paths.
8
40
  */
9
- export function redactUrl(raw) {
10
- const queryStart = raw.indexOf('?');
11
- if (queryStart === -1)
12
- return raw;
13
- const base = raw.slice(0, queryStart);
14
- const rest = raw.slice(queryStart + 1);
15
- const hashStart = rest.indexOf('#');
16
- const query = hashStart === -1 ? rest : rest.slice(0, hashStart);
17
- const hash = hashStart === -1 ? '' : rest.slice(hashStart);
18
- const params = new URLSearchParams(query);
19
- let changed = false;
20
- for (const key of [...params.keys()]) {
21
- if (isSensitiveKey(key)) {
22
- params.set(key, REDACTED_VALUE);
23
- changed = true;
24
- }
41
+ function projectRequestBody(body, captureBodies) {
42
+ if (!captureBodies)
43
+ return {};
44
+ let text;
45
+ let contentType = 'application/json';
46
+ if (typeof body === 'string') {
47
+ text = body;
48
+ }
49
+ else if (typeof URLSearchParams !== 'undefined' && body instanceof URLSearchParams) {
50
+ text = body.toString();
51
+ contentType = 'application/x-www-form-urlencoded';
25
52
  }
26
- return changed ? `${base}?${params.toString()}${hash}` : raw;
53
+ else if (body !== undefined && body !== null) {
54
+ const shape = body.constructor?.name ?? typeof body;
55
+ return { requestBodyType: shape };
56
+ }
57
+ if (text === undefined || text.length === 0)
58
+ return {};
59
+ const { body: out, truncated } = projectBody(text, contentType);
60
+ return truncated ? { requestBody: out, requestBodyTruncated: true } : { requestBody: out };
61
+ }
62
+ /**
63
+ * Response metadata that needs no body capture: HTTP status text, content-type, and byte size (from
64
+ * content-length when the server sent it). Lets an agent tell an HTML error page served as 200 from
65
+ * real JSON, and spot empty/oversized responses. Fields are omitted when absent so a clean call stays
66
+ * token-flat.
67
+ */
68
+ function netResponseMeta(statusText, contentType, contentLength) {
69
+ const out = {};
70
+ if (statusText !== '')
71
+ out['statusText'] = statusText;
72
+ if (contentType !== null && contentType !== '')
73
+ out['contentType'] = contentType;
74
+ const size = contentLength !== null ? Number.parseInt(contentLength, 10) : Number.NaN;
75
+ if (Number.isFinite(size))
76
+ out['responseSize'] = size;
77
+ return out;
27
78
  }
28
79
  function urlOf(input) {
29
80
  if (typeof input === 'string')
@@ -39,12 +90,125 @@ function methodOf(input, init) {
39
90
  return input.method.toUpperCase();
40
91
  return 'GET';
41
92
  }
93
+ /**
94
+ * The first app-code frame that fired a request — the in-page answer to a CDP initiator, as file:line.
95
+ * Captured from a fresh Error.stack at call time, skipping Reticle's own wrapper frames. Feeds the
96
+ * causal chain (which code path made this request). Capped; undefined when no stack is available.
97
+ * ponytail: one stack unwind per request — cheap next to fetch itself; revisit only if a profiler flags it.
98
+ */
99
+ /**
100
+ * Frames to skip: Reticle's own wrappers + engine-internal frames with no app source location.
101
+ * Anchored to Reticle's actual module paths (`@reticlehq/…`, the SDK's own `.ts` files) — a bare
102
+ * `reticle` alternative matched ANY app whose bundle URL merely contained the word (including this
103
+ * repo's own dogfood fixtures served under `/reticle/`), silently dropping their initiatorStack.
104
+ */
105
+ const NON_APP_FRAME = /@reticlehq|reticle\.ts|network\.ts|transport\.ts|<anonymous>|new Promise|node:internal/i;
106
+ /** Pure: the first real app-code frame in a stack string, capped. Exported for unit testing. */
107
+ export function firstAppFrame(stack) {
108
+ if (stack === undefined)
109
+ return undefined;
110
+ for (const line of stack.split('\n').slice(1)) {
111
+ if (NON_APP_FRAME.test(line))
112
+ continue;
113
+ const trimmed = line.trim();
114
+ if (trimmed.length === 0)
115
+ continue;
116
+ return trimmed.slice(0, 300);
117
+ }
118
+ return undefined;
119
+ }
120
+ function initiatorFrame() {
121
+ return firstAppFrame(new Error().stack);
122
+ }
123
+ /**
124
+ * Pure: derive TTFB + transfer size from a PerformanceResourceTiming entry. TTFB = responseStart -
125
+ * requestStart; cross-origin responses zero those (Timing-Allow-Origin), so we omit rather than report a
126
+ * bogus 0. Exported for unit testing (jsdom doesn't post real resource entries).
127
+ */
128
+ export function extractTiming(entry) {
129
+ if (entry === undefined)
130
+ return {};
131
+ const timing = {};
132
+ if (entry.responseStart > 0 && entry.requestStart > 0) {
133
+ timing.ttfbMs = Math.round(entry.responseStart - entry.requestStart);
134
+ }
135
+ if (entry.transferSize > 0)
136
+ timing.transferSize = entry.transferSize;
137
+ return timing;
138
+ }
139
+ /** Best-effort lookup of the most-recent resource-timing entry for a URL. */
140
+ function resourceTiming(rawUrl) {
141
+ try {
142
+ const entries = performance.getEntriesByName(rawUrl, 'resource');
143
+ return extractTiming(entries[entries.length - 1]);
144
+ }
145
+ catch {
146
+ return {};
147
+ }
148
+ }
42
149
  /** Patch fetch + XMLHttpRequest to emit net.request events. Fully reversible. */
43
- export function installNetwork(emit) {
150
+ /**
151
+ * True for Reticle's OWN bridge connection, which must never be instrumented.
152
+ *
153
+ * The transport resolves `WebSocket` at call time, so a reconnect after instrumentation constructs a
154
+ * PATCHED socket. From then on emitting an event calls transport.send -> the patched send emits a
155
+ * NET_STREAM event -> which calls transport.send again, until the stack blows and the page is dead.
156
+ * Keyed on the bridge PATH rather than the host: an app's own socket on the same origin must still be
157
+ * observed, otherwise this guard would blind the stream category it exists to protect.
158
+ */
159
+ function isBridgeSocket(url) {
160
+ try {
161
+ return new URL(url, location.href).pathname === RETICLE_WS_PATH;
162
+ }
163
+ catch {
164
+ return url.includes(RETICLE_WS_PATH);
165
+ }
166
+ }
167
+ /**
168
+ * Whether a function is the platform's own fetch rather than someone's wrapper.
169
+ *
170
+ * `Function.prototype.toString` on a built-in yields "[native code]"; a JS wrapper yields its source.
171
+ * Called off the prototype deliberately, so a wrapper cannot hide behind its own `toString`.
172
+ *
173
+ * Two known limits, both stated in tests rather than left to be discovered:
174
+ * - a BOUND wrapper (`window.fetch = mine.bind(x)`) also reports "[native code]", so it is missed.
175
+ * Nothing in the platform separates the two.
176
+ * - a POLYFILLED fetch reads as wrapped and IS reported — correctly, since a polyfill is a layer we
177
+ * cannot see through, though it will look like a false positive to anyone triaging it.
178
+ *
179
+ * Both failure modes are safe: we under-report on the first and over-report on the second, and
180
+ * over-reporting a coverage caveat is the direction this library errs in everywhere else.
181
+ */
182
+ function isNativeFetch(fn) {
183
+ try {
184
+ return Function.prototype.toString.call(fn).includes('native code');
185
+ }
186
+ catch {
187
+ return false;
188
+ }
189
+ }
190
+ /** Wrappers this module installed, so a re-install does not report itself as a foreign wrapper. */
191
+ const OURS = new WeakSet();
192
+ export function installNetwork(emit, opts = {}) {
193
+ const captureBodies = opts.captureBodies === true;
44
194
  // Keep the true original for teardown identity, plus a window-bound copy to invoke
45
195
  // (fetch throws "Illegal invocation" if called with the wrong `this`).
46
196
  const origFetch = window.fetch;
47
197
  const callFetch = origFetch.bind(window);
198
+ // Declare it if we are not the first to wrap fetch.
199
+ //
200
+ // Wrappers chain outermost-first, and we record `init.body` when OUR wrapper runs — so anything
201
+ // installed EARLIER sits below us and mutates the request after we have read it. That is a real
202
+ // blind spot (an auth/analytics interceptor started before connect(), a polyfill, a service worker
203
+ // is worse still) and it is not fixable from in here: there is no "patch last" primitive, and
204
+ // racing for outermost loses to whatever loads after us.
205
+ //
206
+ // So it is reported rather than hidden, on the same contract as the cross-origin-iframe sensor —
207
+ // say what we cannot see, so a green verdict never implies we saw it. `isOurs` keeps a re-install
208
+ // from blaming the app for our own wrapper.
209
+ if (!isNativeFetch(origFetch) && !OURS.has(origFetch)) {
210
+ emit(EventType.BLIND_SPOT, { kind: BlindSpotKind.WRAPPED_NETWORK, count: 1 });
211
+ }
48
212
  // Correlation id so a NET_PENDING (emitted at request START) can be matched to its
49
213
  // NET_REQUEST completion. A request that never completes leaves an unmatched NET_PENDING —
50
214
  // that is how a hung/in-flight request becomes observable (it never resolves, so the old
@@ -55,19 +219,82 @@ export function installNetwork(emit) {
55
219
  const id = nextId();
56
220
  const start = performance.now();
57
221
  const method = methodOf(input, init);
58
- const url = redactUrl(urlOf(input));
59
- emit(EventType.NET_PENDING, { id, method, url, initiator: 'fetch' });
222
+ const rawUrl = urlOf(input);
223
+ const url = redactUrl(rawUrl);
224
+ const initiatorStack = initiatorFrame();
225
+ const initiatorFields = initiatorStack === undefined ? {} : { initiatorStack };
226
+ emit(EventType.NET_PENDING, { id, method, url, initiator: 'fetch', ...initiatorFields });
60
227
  try {
61
228
  const res = await callFetch(input, init);
62
- emit(EventType.NET_REQUEST, {
63
- id,
64
- method,
65
- url,
66
- status: res.status,
67
- ok: res.ok,
68
- durationMs: Math.round(performance.now() - start),
69
- initiator: 'fetch',
70
- });
229
+ // The app's fetch resolves HERE — at headers — like a native fetch. durationMs is measured to
230
+ // headers-received, so it stays honest whether or not we read the body.
231
+ const headersAt = performance.now();
232
+ const contentType = res.headers.get('content-type');
233
+ const emitRequest = (responseBodyFields) => {
234
+ emit(EventType.NET_REQUEST, {
235
+ id,
236
+ method,
237
+ url,
238
+ status: res.status,
239
+ ok: res.ok,
240
+ durationMs: Math.round(headersAt - start),
241
+ initiator: 'fetch',
242
+ ...initiatorFields,
243
+ ...resourceTiming(rawUrl),
244
+ ...netResponseMeta(res.statusText, contentType, res.headers.get('content-length')),
245
+ ...projectRequestBody(init?.body, captureBodies),
246
+ ...responseBodyFields,
247
+ });
248
+ };
249
+ if (captureBodies && isCapturableType(contentType)) {
250
+ // ONLY the body read can make the app wait (a chunked response with no content-length can be
251
+ // arbitrarily long). Clone synchronously so the app's stream is untouched, then read + emit from
252
+ // a DETACHED promise — the app already has res, so our bounded read is invisible to it. Without
253
+ // body capture (the DEFAULT) we emit synchronously below, exactly as before: no latency, no
254
+ // deferral, NET_REQUEST in order.
255
+ //
256
+ // Tradeoff, opt-in path only: under captureBodies the NET_REQUEST for THIS call lands after the
257
+ // bounded body read (≤ the deadline), so it can arrive out of order vs a later request's
258
+ // NET_PENDING, and a BARE `assert { net, count }` fired the instant the app's fetch resolves may
259
+ // see the count not-yet-incremented. Use `wait_for` for count/settle assertions when body
260
+ // capture is on (it already polls until the event lands). The default path has neither caveat.
261
+ let clone;
262
+ try {
263
+ clone = res.clone();
264
+ }
265
+ catch {
266
+ /* already consumed/locked — emit the envelope with no body */
267
+ }
268
+ // The whole IIFE is guarded: emit is the SDK's already-try/catch'd sink today, but a detached
269
+ // promise must never be able to surface an unhandledrejection into the host page even if a
270
+ // future caller passes a throwing emit. A body we can't read is simply dropped.
271
+ void (async () => {
272
+ let responseBodyFields = {};
273
+ if (clone !== undefined) {
274
+ try {
275
+ const text = await withBodyDeadline(clone.text());
276
+ if (text !== undefined) {
277
+ const { body, truncated } = projectBody(text, contentType);
278
+ responseBodyFields = truncated
279
+ ? { responseBody: body, responseBodyTruncated: true }
280
+ : { responseBody: body };
281
+ }
282
+ }
283
+ catch {
284
+ /* body not readable — skip, keep the envelope */
285
+ }
286
+ }
287
+ try {
288
+ emitRequest(responseBodyFields);
289
+ }
290
+ catch {
291
+ /* observation is best-effort; never reject into the page */
292
+ }
293
+ })().catch(() => undefined);
294
+ }
295
+ else {
296
+ emitRequest({});
297
+ }
71
298
  return res;
72
299
  }
73
300
  catch (error) {
@@ -80,49 +307,208 @@ export function installNetwork(emit) {
80
307
  error: error instanceof Error ? error.message : String(error),
81
308
  durationMs: Math.round(performance.now() - start),
82
309
  initiator: 'fetch',
310
+ ...initiatorFields,
83
311
  });
84
312
  throw error;
85
313
  }
86
314
  };
315
+ // Remember it, so a later install recognises our own wrapper instead of reporting the app.
316
+ OURS.add(window.fetch);
317
+ const patchedFetch = window.fetch;
87
318
  const meta = new WeakMap();
88
319
  const proto = XMLHttpRequest.prototype;
89
- /* eslint-disable @typescript-eslint/unbound-method -- captured to re-invoke via .call(this) */
90
- const origOpen = proto.open;
91
- const origSend = proto.send;
92
- /* eslint-enable @typescript-eslint/unbound-method */
320
+ const origOpen = captureMethod(proto, 'open');
321
+ const origSend = captureMethod(proto, 'send');
93
322
  const callOpen = origOpen;
94
323
  proto.open = function (method, url, ...rest) {
95
324
  meta.set(this, {
96
325
  id: nextId(),
97
326
  method: method.toUpperCase(),
98
327
  url: redactUrl(String(url)),
328
+ rawUrl: String(url),
99
329
  start: 0,
100
330
  });
101
331
  callOpen.call(this, method, url, ...rest);
102
332
  };
333
+ const patchedOpen = captureMethod(proto, 'open');
334
+ // A reused XHR calls send repeatedly; attach the completion listener ONCE per instance and read the
335
+ // request identity from `meta` at fire time. Adding a fresh closure each send would leave stale
336
+ // listeners that re-fire on later completions, emitting duplicate, mislabeled events.
337
+ const listenerAttached = new WeakSet();
103
338
  proto.send = function (body) {
104
339
  const m = meta.get(this);
105
340
  if (m !== undefined) {
106
341
  m.start = performance.now();
107
- emit(EventType.NET_PENDING, { id: m.id, method: m.method, url: m.url, initiator: 'xhr' });
108
- this.addEventListener('loadend', () => {
109
- emit(EventType.NET_REQUEST, {
110
- id: m.id,
111
- method: m.method,
112
- url: m.url,
113
- status: this.status,
114
- ok: this.status >= 200 && this.status < 400,
115
- durationMs: Math.round(performance.now() - m.start),
116
- initiator: 'xhr',
117
- });
342
+ m.reqBody = body ?? null;
343
+ m.initiatorStack = initiatorFrame(); // the app's xhr.send call site
344
+ const initiatorFields = m.initiatorStack === undefined ? {} : { initiatorStack: m.initiatorStack };
345
+ emit(EventType.NET_PENDING, {
346
+ id: m.id,
347
+ method: m.method,
348
+ url: m.url,
349
+ initiator: 'xhr',
350
+ ...initiatorFields,
118
351
  });
352
+ if (!listenerAttached.has(this)) {
353
+ listenerAttached.add(this);
354
+ this.addEventListener('loadend', () => {
355
+ const cur = meta.get(this);
356
+ if (cur === undefined)
357
+ return;
358
+ const xhrContentType = this.getResponseHeader('content-type');
359
+ let responseBodyFields = {};
360
+ // responseText throws unless responseType is '' or 'text' — guard before reading.
361
+ const textReadable = this.responseType === '' || this.responseType === 'text';
362
+ if (captureBodies && textReadable && isCapturableType(xhrContentType)) {
363
+ try {
364
+ const { body: rb, truncated } = projectBody(this.responseText, xhrContentType);
365
+ responseBodyFields = truncated
366
+ ? { responseBody: rb, responseBodyTruncated: true }
367
+ : { responseBody: rb };
368
+ }
369
+ catch {
370
+ /* unreadable body — skip */
371
+ }
372
+ }
373
+ emit(EventType.NET_REQUEST, {
374
+ id: cur.id,
375
+ method: cur.method,
376
+ url: cur.url,
377
+ status: this.status,
378
+ ok: this.status >= 200 && this.status < 400,
379
+ durationMs: Math.round(performance.now() - cur.start),
380
+ initiator: 'xhr',
381
+ ...(cur.initiatorStack === undefined ? {} : { initiatorStack: cur.initiatorStack }),
382
+ ...resourceTiming(cur.rawUrl),
383
+ ...netResponseMeta(this.statusText, xhrContentType, this.getResponseHeader('content-length')),
384
+ ...projectRequestBody(cur.reqBody, captureBodies),
385
+ ...responseBodyFields,
386
+ });
387
+ });
388
+ }
119
389
  }
120
390
  origSend.call(this, body ?? null);
121
391
  };
392
+ const patchedSend = captureMethod(proto, 'send');
393
+ // SSE + WebSocket frame capture — gated behind body capture, since a chatty stream is the
394
+ // high-volume case. Subclass the native constructors so the app's own usage is unchanged.
395
+ const origEventSource = window.EventSource;
396
+ const origWebSocket = window.WebSocket;
397
+ let patchedEventSource;
398
+ let patchedWebSocket;
399
+ if (captureBodies && typeof origEventSource === 'function') {
400
+ window.EventSource = class extends origEventSource {
401
+ constructor(u, init) {
402
+ super(u, init);
403
+ const url = redactUrl(String(u));
404
+ emit(EventType.NET_STREAM, {
405
+ transport: StreamTransport.SSE,
406
+ direction: StreamDirection.OPEN,
407
+ url,
408
+ });
409
+ this.addEventListener('message', (ev) => {
410
+ emit(EventType.NET_STREAM, {
411
+ transport: StreamTransport.SSE,
412
+ direction: StreamDirection.IN,
413
+ url,
414
+ ...frameFields(ev.data, captureBodies),
415
+ });
416
+ });
417
+ }
418
+ };
419
+ patchedEventSource = window.EventSource;
420
+ }
421
+ if (captureBodies && typeof origWebSocket === 'function') {
422
+ window.WebSocket = class extends origWebSocket {
423
+ /** Reticle's own bridge socket is never observed — see isBridgeSocket. */
424
+ #isBridge;
425
+ constructor(u, protocols) {
426
+ super(u, protocols);
427
+ this.#isBridge = isBridgeSocket(String(u));
428
+ if (this.#isBridge)
429
+ return;
430
+ const url = redactUrl(String(u));
431
+ emit(EventType.NET_STREAM, {
432
+ transport: StreamTransport.WS,
433
+ direction: StreamDirection.OPEN,
434
+ url,
435
+ });
436
+ this.addEventListener('message', (ev) => {
437
+ emit(EventType.NET_STREAM, {
438
+ transport: StreamTransport.WS,
439
+ direction: StreamDirection.IN,
440
+ url,
441
+ ...frameFields(ev.data, captureBodies),
442
+ });
443
+ });
444
+ }
445
+ send(data) {
446
+ if (this.#isBridge) {
447
+ super.send(data);
448
+ return;
449
+ }
450
+ emit(EventType.NET_STREAM, {
451
+ transport: StreamTransport.WS,
452
+ direction: StreamDirection.OUT,
453
+ url: redactUrl(this.url),
454
+ ...frameFields(data, captureBodies),
455
+ });
456
+ super.send(data);
457
+ }
458
+ };
459
+ patchedWebSocket = window.WebSocket;
460
+ }
461
+ // navigator.sendBeacon — fire-and-forget analytics/telemetry, invisible to fetch/XHR wrapping. A page
462
+ // that beacons a "checkout completed" event should show it. Patch the instance's prototype (via
463
+ // getPrototypeOf, robust whether or not the Navigator global exists); the descriptor read avoids an
464
+ // unbound-method access; the send is synchronous so we emit one completed NET_REQUEST with its result.
465
+ const navProto = (typeof navigator !== 'undefined' ? Object.getPrototypeOf(navigator) : null);
466
+ const origBeacon = (navProto === null ? undefined : Object.getOwnPropertyDescriptor(navProto, 'sendBeacon')?.value);
467
+ let patchedBeacon;
468
+ if (navProto !== null && origBeacon !== undefined) {
469
+ patchedBeacon = function (url, data) {
470
+ const id = nextId();
471
+ const redacted = redactUrl(String(url));
472
+ const initiatorStack = initiatorFrame();
473
+ const sent = origBeacon.call(this, url, data);
474
+ // sendBeacon returns whether the payload was QUEUED, not an HTTP result — the response never
475
+ // surfaces to JS. Fabricating status 200 lied to an agent asserting on status. Report status 0
476
+ // (no HTTP response observed) and carry the real signal in `queued`.
477
+ emit(EventType.NET_REQUEST, {
478
+ id,
479
+ method: 'POST',
480
+ url: redacted,
481
+ status: 0,
482
+ ok: sent,
483
+ queued: sent,
484
+ durationMs: 0,
485
+ initiator: 'beacon',
486
+ ...(initiatorStack === undefined ? {} : { initiatorStack }),
487
+ });
488
+ return sent;
489
+ };
490
+ navProto.sendBeacon = patchedBeacon;
491
+ }
122
492
  return () => {
123
- window.fetch = origFetch;
124
- proto.open = origOpen;
125
- proto.send = origSend;
493
+ // Restore each slot ONLY if it still holds OUR wrapper. Between connect() and disconnect() the app
494
+ // (or Sentry/analytics/a router) may have wrapped fetch/XHR/EventSource/WebSocket/sendBeacon ON TOP
495
+ // of ours; blindly writing the original back would silently uninstall their instrumentation — the
496
+ // dev-only SDK breaking the app it only meant to observe.
497
+ if (window.fetch === patchedFetch)
498
+ window.fetch = origFetch;
499
+ if (captureMethod(proto, 'open') === patchedOpen)
500
+ proto.open = origOpen;
501
+ if (captureMethod(proto, 'send') === patchedSend)
502
+ proto.send = origSend;
503
+ if (patchedEventSource !== undefined && window.EventSource === patchedEventSource) {
504
+ window.EventSource = origEventSource;
505
+ }
506
+ if (patchedWebSocket !== undefined && window.WebSocket === patchedWebSocket) {
507
+ window.WebSocket = origWebSocket;
508
+ }
509
+ if (navProto !== null && origBeacon !== undefined && navProto.sendBeacon === patchedBeacon) {
510
+ navProto.sendBeacon = origBeacon;
511
+ }
126
512
  };
127
513
  }
128
514
  //# sourceMappingURL=network.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"network.js","sourceRoot":"","sources":["../../src/observers/network.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"network.js","sourceRoot":"","sources":["../../src/observers/network.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { Emit, Teardown } from './types.js';
2
+ /**
3
+ * Observe the web-perf signals a screenshot tool fundamentally cannot verify — largest-contentful-paint
4
+ * (LCP), cumulative layout shift (CLS), and long tasks — and emit them into the ring buffer so an agent
5
+ * can assert "no layout shift on load" or "LCP under 2.5s". No-ops when PerformanceObserver or a given
6
+ * entry type is unavailable (jsdom / older browsers), so it never throws in an unsupported context.
7
+ *
8
+ * Each event carries `at` (the entry's own startTime) so a consumer can reason about WHEN the metric
9
+ * occurred rather than when it was flushed — buffered:true replays pre-install entries, whose emit time
10
+ * would otherwise be install time.
11
+ */
12
+ export declare function installPerf(emit: Emit): Teardown;
13
+ //# sourceMappingURL=perf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"perf.d.ts","sourceRoot":"","sources":["../../src/observers/perf.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAQjD;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,QAAQ,CA8ChD"}