@newrelic/browser-agent 1.286.0 → 1.288.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 (162) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/cjs/common/config/init-types.js +96 -0
  3. package/dist/cjs/common/config/init.js +9 -79
  4. package/dist/cjs/common/config/runtime.js +7 -6
  5. package/dist/cjs/common/constants/env.cdn.js +1 -1
  6. package/dist/cjs/common/constants/env.npm.js +1 -1
  7. package/dist/cjs/common/harvest/harvester.js +2 -2
  8. package/dist/cjs/common/session/session-entity.js +10 -3
  9. package/dist/cjs/common/util/feature-flags.js +4 -5
  10. package/dist/cjs/common/util/target.js +34 -0
  11. package/dist/cjs/features/ajax/aggregate/index.js +2 -1
  12. package/dist/cjs/features/generic_events/aggregate/index.js +10 -6
  13. package/dist/cjs/features/jserrors/aggregate/index.js +44 -22
  14. package/dist/cjs/features/logging/aggregate/index.js +21 -13
  15. package/dist/cjs/features/logging/shared/utils.js +3 -2
  16. package/dist/cjs/features/metrics/aggregate/index.js +6 -4
  17. package/dist/cjs/features/page_view_event/aggregate/index.js +60 -11
  18. package/dist/cjs/features/page_view_event/instrument/index.js +4 -0
  19. package/dist/cjs/features/session_replay/aggregate/index.js +9 -7
  20. package/dist/cjs/features/session_replay/instrument/index.js +1 -1
  21. package/dist/cjs/features/session_replay/shared/recorder-events.js +4 -2
  22. package/dist/cjs/features/session_replay/shared/recorder.js +17 -11
  23. package/dist/cjs/features/session_trace/aggregate/trace/storage.js +8 -1
  24. package/dist/cjs/features/soft_navigations/aggregate/index.js +13 -2
  25. package/dist/cjs/features/spa/aggregate/index.js +4 -3
  26. package/dist/cjs/features/spa/aggregate/interaction.js +6 -9
  27. package/dist/cjs/features/utils/aggregate-base.js +49 -20
  28. package/dist/cjs/features/utils/entity-manager.js +47 -0
  29. package/dist/cjs/features/utils/event-store-manager.js +79 -54
  30. package/dist/cjs/interfaces/registered-entity.js +114 -0
  31. package/dist/cjs/loaders/api/api-methods.js +1 -1
  32. package/dist/cjs/loaders/api/api.js +50 -18
  33. package/dist/cjs/loaders/api/register-api-types.js +35 -0
  34. package/dist/cjs/loaders/api/register-api.js +165 -0
  35. package/dist/cjs/loaders/micro-agent-base.js +16 -0
  36. package/dist/cjs/loaders/micro-agent.js +1 -0
  37. package/dist/esm/common/config/init-types.js +92 -0
  38. package/dist/esm/common/config/init.js +9 -79
  39. package/dist/esm/common/config/runtime.js +7 -6
  40. package/dist/esm/common/constants/env.cdn.js +1 -1
  41. package/dist/esm/common/constants/env.npm.js +1 -1
  42. package/dist/esm/common/harvest/harvester.js +2 -2
  43. package/dist/esm/common/session/session-entity.js +10 -3
  44. package/dist/esm/common/util/feature-flags.js +4 -5
  45. package/dist/esm/common/util/target.js +27 -0
  46. package/dist/esm/features/ajax/aggregate/index.js +2 -1
  47. package/dist/esm/features/generic_events/aggregate/index.js +10 -6
  48. package/dist/esm/features/jserrors/aggregate/index.js +44 -22
  49. package/dist/esm/features/logging/aggregate/index.js +21 -13
  50. package/dist/esm/features/logging/shared/utils.js +3 -2
  51. package/dist/esm/features/metrics/aggregate/index.js +6 -4
  52. package/dist/esm/features/page_view_event/aggregate/index.js +60 -11
  53. package/dist/esm/features/page_view_event/instrument/index.js +4 -0
  54. package/dist/esm/features/session_replay/aggregate/index.js +9 -7
  55. package/dist/esm/features/session_replay/instrument/index.js +1 -1
  56. package/dist/esm/features/session_replay/shared/recorder-events.js +4 -2
  57. package/dist/esm/features/session_replay/shared/recorder.js +17 -11
  58. package/dist/esm/features/session_trace/aggregate/trace/storage.js +8 -1
  59. package/dist/esm/features/soft_navigations/aggregate/index.js +13 -2
  60. package/dist/esm/features/spa/aggregate/index.js +4 -3
  61. package/dist/esm/features/spa/aggregate/interaction.js +6 -9
  62. package/dist/esm/features/utils/aggregate-base.js +49 -20
  63. package/dist/esm/features/utils/entity-manager.js +40 -0
  64. package/dist/esm/features/utils/event-store-manager.js +79 -54
  65. package/dist/esm/interfaces/registered-entity.js +107 -0
  66. package/dist/esm/loaders/api/api-methods.js +1 -1
  67. package/dist/esm/loaders/api/api.js +50 -18
  68. package/dist/esm/loaders/api/register-api-types.js +33 -0
  69. package/dist/esm/loaders/api/register-api.js +159 -0
  70. package/dist/esm/loaders/micro-agent-base.js +16 -0
  71. package/dist/esm/loaders/micro-agent.js +1 -0
  72. package/dist/tsconfig.tsbuildinfo +1 -1
  73. package/dist/types/common/config/init-types.d.ts +275 -0
  74. package/dist/types/common/config/init-types.d.ts.map +1 -0
  75. package/dist/types/common/config/init.d.ts +1 -262
  76. package/dist/types/common/config/init.d.ts.map +1 -1
  77. package/dist/types/common/config/runtime.d.ts.map +1 -1
  78. package/dist/types/common/session/session-entity.d.ts +3 -1
  79. package/dist/types/common/session/session-entity.d.ts.map +1 -1
  80. package/dist/types/common/util/feature-flags.d.ts +1 -1
  81. package/dist/types/common/util/feature-flags.d.ts.map +1 -1
  82. package/dist/types/common/util/target.d.ts +18 -0
  83. package/dist/types/common/util/target.d.ts.map +1 -0
  84. package/dist/types/features/ajax/aggregate/index.d.ts +1 -1
  85. package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
  86. package/dist/types/features/generic_events/aggregate/index.d.ts +2 -1
  87. package/dist/types/features/generic_events/aggregate/index.d.ts.map +1 -1
  88. package/dist/types/features/jserrors/aggregate/index.d.ts +9 -1
  89. package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
  90. package/dist/types/features/logging/aggregate/index.d.ts +3 -3
  91. package/dist/types/features/logging/aggregate/index.d.ts.map +1 -1
  92. package/dist/types/features/logging/shared/utils.d.ts +2 -1
  93. package/dist/types/features/logging/shared/utils.d.ts.map +1 -1
  94. package/dist/types/features/metrics/aggregate/index.d.ts +1 -0
  95. package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
  96. package/dist/types/features/page_view_event/aggregate/index.d.ts +10 -2
  97. package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
  98. package/dist/types/features/page_view_event/instrument/index.d.ts.map +1 -1
  99. package/dist/types/features/session_replay/aggregate/index.d.ts +3 -12
  100. package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
  101. package/dist/types/features/session_replay/shared/recorder-events.d.ts +1 -0
  102. package/dist/types/features/session_replay/shared/recorder-events.d.ts.map +1 -1
  103. package/dist/types/features/session_replay/shared/recorder.d.ts +5 -5
  104. package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -1
  105. package/dist/types/features/session_trace/aggregate/trace/storage.d.ts +1 -0
  106. package/dist/types/features/session_trace/aggregate/trace/storage.d.ts.map +1 -1
  107. package/dist/types/features/soft_navigations/aggregate/index.d.ts.map +1 -1
  108. package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
  109. package/dist/types/features/spa/aggregate/interaction.d.ts +3 -4
  110. package/dist/types/features/spa/aggregate/interaction.d.ts.map +1 -1
  111. package/dist/types/features/utils/aggregate-base.d.ts +22 -5
  112. package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
  113. package/dist/types/features/utils/entity-manager.d.ts +15 -0
  114. package/dist/types/features/utils/entity-manager.d.ts.map +1 -0
  115. package/dist/types/features/utils/event-store-manager.d.ts +48 -24
  116. package/dist/types/features/utils/event-store-manager.d.ts.map +1 -1
  117. package/dist/types/interfaces/registered-entity.d.ts +72 -0
  118. package/dist/types/interfaces/registered-entity.d.ts.map +1 -0
  119. package/dist/types/loaders/agent.d.ts +1 -1
  120. package/dist/types/loaders/api/api.d.ts.map +1 -1
  121. package/dist/types/loaders/api/register-api-types.d.ts +56 -0
  122. package/dist/types/loaders/api/register-api-types.d.ts.map +1 -0
  123. package/dist/types/loaders/api/register-api.d.ts +14 -0
  124. package/dist/types/loaders/api/register-api.d.ts.map +1 -0
  125. package/dist/types/loaders/micro-agent-base.d.ts +17 -0
  126. package/dist/types/loaders/micro-agent-base.d.ts.map +1 -1
  127. package/dist/types/loaders/micro-agent.d.ts +1 -0
  128. package/dist/types/loaders/micro-agent.d.ts.map +1 -1
  129. package/package.json +10 -1
  130. package/src/common/config/init-types.js +92 -0
  131. package/src/common/config/init.js +9 -79
  132. package/src/common/config/runtime.js +7 -6
  133. package/src/common/harvest/harvester.js +2 -2
  134. package/src/common/session/session-entity.js +10 -3
  135. package/src/common/util/feature-flags.js +4 -5
  136. package/src/common/util/target.js +27 -0
  137. package/src/features/ajax/aggregate/index.js +2 -1
  138. package/src/features/generic_events/aggregate/index.js +8 -6
  139. package/src/features/jserrors/aggregate/index.js +42 -20
  140. package/src/features/logging/aggregate/index.js +18 -12
  141. package/src/features/logging/shared/utils.js +3 -2
  142. package/src/features/metrics/aggregate/index.js +7 -5
  143. package/src/features/page_view_event/aggregate/index.js +50 -8
  144. package/src/features/page_view_event/instrument/index.js +4 -0
  145. package/src/features/session_replay/aggregate/index.js +7 -4
  146. package/src/features/session_replay/instrument/index.js +1 -1
  147. package/src/features/session_replay/shared/recorder-events.js +5 -2
  148. package/src/features/session_replay/shared/recorder.js +17 -11
  149. package/src/features/session_trace/aggregate/trace/storage.js +9 -1
  150. package/src/features/soft_navigations/aggregate/index.js +12 -2
  151. package/src/features/spa/aggregate/index.js +4 -3
  152. package/src/features/spa/aggregate/interaction.js +6 -9
  153. package/src/features/utils/aggregate-base.js +54 -22
  154. package/src/features/utils/entity-manager.js +45 -0
  155. package/src/features/utils/event-store-manager.js +72 -49
  156. package/src/interfaces/registered-entity.js +107 -0
  157. package/src/loaders/api/api-methods.js +1 -1
  158. package/src/loaders/api/api.js +49 -13
  159. package/src/loaders/api/register-api-types.js +33 -0
  160. package/src/loaders/api/register-api.js +152 -0
  161. package/src/loaders/micro-agent-base.js +16 -0
  162. package/src/loaders/micro-agent.js +1 -0
package/CHANGELOG.md CHANGED
@@ -3,6 +3,27 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [1.288.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.287.0...v1.288.0) (2025-04-16)
7
+
8
+
9
+ ### Features
10
+
11
+ * Introduce isFirstOfSession attribute on InitialPageLoad events ([#1432](https://github.com/newrelic/newrelic-browser-agent/issues/1432)) ([8d7bdd6](https://github.com/newrelic/newrelic-browser-agent/commit/8d7bdd63abe0b6d9dfccc46f63845bde0fd099a4))
12
+ * Prevent storing session data past session expiry ([#1426](https://github.com/newrelic/newrelic-browser-agent/issues/1426)) ([5819b64](https://github.com/newrelic/newrelic-browser-agent/commit/5819b649792b6227d49173ecb326f918b1f39bdb))
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * Reset `notified` when replay stops recording ([#1435](https://github.com/newrelic/newrelic-browser-agent/issues/1435)) ([7dd8b62](https://github.com/newrelic/newrelic-browser-agent/commit/7dd8b6217763c57c382737b6ff90667066437b75))
18
+ * Solve race condition in logging abort ([#1445](https://github.com/newrelic/newrelic-browser-agent/issues/1445)) ([ab315dc](https://github.com/newrelic/newrelic-browser-agent/commit/ab315dc009a45911911f5d176978fac0cf066be3))
19
+
20
+ ## [1.287.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.286.0...v1.287.0) (2025-04-10)
21
+
22
+
23
+ ### Features
24
+
25
+ * Central Agent Architecture - Micro Front Ends ([#1266](https://github.com/newrelic/newrelic-browser-agent/issues/1266)) ([b1a6c30](https://github.com/newrelic/newrelic-browser-agent/commit/b1a6c30bf78001f5286a614c229ceb7a256593aa))
26
+
6
27
  ## [1.286.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.285.0...v1.286.0) (2025-04-01)
7
28
 
8
29
 
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ /**
8
+ * Copyright 2020-2025 New Relic, Inc. All rights reserved.
9
+ * SPDX-License-Identifier: Apache-2.0
10
+ *
11
+ */
12
+ /**
13
+ * @typedef {Object} Init
14
+ * @property {Object} [ajax]
15
+ * @property {Array<string>} [ajax.deny_list] - List of domain URLs to be excluded from AjaxRequest collection.
16
+ * @property {boolean} [ajax.block_internal] - If true, agent requests going to harvest endpoint are treated as on deny list. In other words, agent will not self-report AJAX.
17
+ * @property {boolean} [ajax.enabled] - Turn on/off the ajax feature (on by default).
18
+ * @property {boolean} [ajax.autoStart] - If true, the agent will automatically start the ajax feature. Otherwise, it will be in a deferred state until the `start` API method is called.
19
+ * @property {Object} [api]
20
+ * @property {boolean} [api.allow_registered_children] - If true, the agent will allow registered children to be sent to the server.
21
+ * @property {boolean} [api.duplicate_registered_data] - If true, the agent will capture registered child data to the main agent as well as the registered child.
22
+ * @property {Object} [distributed_tracing]
23
+ * @property {boolean} [distributed_tracing.enabled] - If true, distributed tracing headers will be added to outgoing requests. Requires ajax feature to be running.
24
+ * @property {boolean} [distributed_tracing.exclude_newrelic_header]
25
+ * @property {boolean} [distributed_tracing.cors_use_newrelic_header]
26
+ * @property {boolean} [distributed_tracing.cors_use_tracecontext_headers]
27
+ * @property {Array<string>} [distributed_tracing.allowed_origins]
28
+ * @property {Array<string>} [feature_flags] - An array of feature flags to enable experimental features.
29
+ * @property {Object} [generic_events]
30
+ * @property {boolean} [generic_events.enabled] - Turn on/off the generic events feature (on by default). This is required for `PageAction`, `UserAction`, and `BrowserPerformance` events.
31
+ * @property {boolean} [generic_events.autoStart] - If true, the agent will automatically start the generic events feature. Otherwise, it will be in a deferred state until the `start` API method is called.
32
+ * @property {Object} [harvest]
33
+ * @property {number} [harvest.interval] - The interval in seconds at which the agent will send out data. It's not recommended to change this value.
34
+ * @property {Object} [jserrors]
35
+ * @property {boolean} [jserrors.enabled] - Turn on/off the jserrors feature (on by default).
36
+ * @property {boolean} [jserrors.autoStart] - If true, the agent will automatically start the jserrors feature. Otherwise, it will be in a deferred state until the `start` API method is called.
37
+ * @property {Object} [logging]
38
+ * @property {boolean} [logging.enabled] - Turn on/off the logging feature (on by default).
39
+ * @property {boolean} [logging.autoStart] - If true, the agent will automatically start the logging feature. Otherwise, it will be in a deferred state until the `start` API method is called.
40
+ * @property {Object} [metrics]
41
+ * @property {boolean} [metrics.enabled] - Turn on/off the metrics feature (on by default).
42
+ * @property {boolean} [metrics.autoStart] - If true, the agent will automatically start the metrics feature. Otherwise, it will be in a deferred state until the `start` API method is called.
43
+ * @property {Array<Object>} [obfuscate] - Array of regexp and corresponding replacement patterns for obfuscating data.
44
+ * @property {Object} [page_action]
45
+ * @property {boolean} [page_action.enabled] - Must be true to allow PageAction events to be captured.
46
+ * @property {Object} [page_view_event]
47
+ * @property {boolean} [page_view_event.enabled] - This setting is ignored! PageViewEvent is always enabled by force.
48
+ * @property {boolean} [page_view_event.autoStart] - If true, the agent will automatically send the RUM request. Otherwise, it will be in a deferred state until the `start` API method is called.
49
+ * @property {Object} [page_view_timing]
50
+ * @property {boolean} [page_view_timing.enabled] - Turn on/off the page view timing feature (on by default).
51
+ * @property {boolean} [page_view_timing.autoStart] - If true, the agent will automatically start the page view timing feature. Otherwise, it will be in a deferred state until the `start` API method is called.
52
+ * @property {Object} [performance]
53
+ * @property {boolean} [performance.capture_marks] - If true, the agent will capture PerformanceMark events.
54
+ * @property {boolean} [performance.capture_measures] - If true, the agent will capture PerformanceMeasure events.
55
+ * @property {boolean} [performance.capture_detail] - If true, `BrowserPerformance` events from marks and measures will include, as attribute(s), the `detail` metadata provided to `markOptions` and `measureOptions`.
56
+ * @property {Object} [performance.resources]
57
+ * @property {boolean} [performance.resources.enabled] - If true, the agent will capture PerformanceResourceTiming entries.
58
+ * @property {Array<string>} [performance.resources.asset_types] - Array of `initiatorType` strings to filter the desired ResourceTiming entries. By default, all resource types are captured.
59
+ * @property {Array<string>} [performance.resources.first_party_domains] - Each resource URL will be checked against this list to determine if it should be labeled "first party" in the resulting `BrowserPerformance` event.
60
+ * @property {boolean} [performance.resources.ignore_newrelic] - When true (default), resource entries associated with New Relic domains will be ignored.
61
+ * @property {Object} [privacy]
62
+ * @property {boolean} [privacy.cookies_enabled] - If true (default), session tracking of users across page loads is enabled in the agent. This is required for session trace, replay, and session-related features.
63
+ * @property {Object} [proxy]
64
+ * @property {string} [proxy.assets] - Set value will be used to overwrite the webpack asset path used to fetch agent assets.
65
+ * @property {string} [proxy.beacon] - Set value will be used to overwrite the endpoint URL to which we send analytics.
66
+ * @property {Object} [session]
67
+ * @property {number} [session.expiresMs] - When session tracking is on, this determines how long a session will last before expiring. Modifying this value is not recommended.
68
+ * @property {number} [session.inactiveMs] - When session tracking is on, this determines how long a session will last without user activity before expiring. Modifying this value is not recommended.
69
+ * @property {Object} [session_replay]
70
+ * @property {boolean} [session_replay.autoStart] - If true, the agent will automatically start the session replay feature. Otherwise, it will be in a deferred state until the `start` API method is called.
71
+ * @property {boolean} [session_replay.enabled] - Turn on/off the session replay feature (off by default).
72
+ * @property {boolean} [session_replay.preload] - If true, allow the agent to run rrweb recorder immediately instead of waiting until after the window.load event, for new sessions. Existing sessions ignore this setting.
73
+ * @property {number} [session_replay.sampling_rate] - This setting is deprecated and ineffective. Sampling is controlled in New Relic by server-side configuration.
74
+ * @property {number} [session_replay.error_sampling_rate] - This setting is deprecated and ineffective.
75
+ * @property {boolean} [session_replay.collect_fonts] - When true, serialize fonts for collection without public asset url. This is currently broken -- https://github.com/rrweb-io/rrweb/issues/1304.
76
+ * @property {boolean} [session_replay.inline_images] - When true, serialize images for collection without public asset url. Not recommended for use. This is currently for TESTING as it easily generates payloads too large to be harvested.
77
+ * @property {boolean} [session_replay.fix_stylesheets] - When true, tries to fetch any missing stylesheets again to inline in replayer.
78
+ * @property {boolean} [session_replay.mask_all_inputs] - If true, all input content will be masked with asterisks.
79
+ * @property {string} [session_replay.mask_text_selector] - Set value should be in CSS selector syntax and is used to identify matching elements to mask.
80
+ * @property {string} [session_replay.block_selector] - Set value should be in CSS selector syntax and is used to identify matching elements to block.
81
+ * @property {Object} [session_replay.mask_input_options] - If mask_all_inputs is not true, this object will be used to select what input to mask. Passwords are forcibly always masked.
82
+ * @property {Object} [session_trace]
83
+ * @property {boolean} [session_trace.enabled] - Turn on/off the session trace feature (on by default).
84
+ * @property {boolean} [session_trace.autoStart] - If true, the agent will automatically start the session trace feature. Otherwise, it will be in a deferred state until the `start` API method is called.
85
+ * @property {Object} [soft_navigations]
86
+ * @property {boolean} [soft_navigations.enabled] - Turn on/off the soft navigations feature (on by default).
87
+ * @property {boolean} [soft_navigations.autoStart] - If true, the agent will automatically start the soft navigations feature. Otherwise, it will be in a deferred state until the `start` API method is called.
88
+ * @property {Object} [spa]
89
+ * @property {boolean} [spa.enabled] - Turn on/off the single page application feature (on by default). NOTE: the SPA feature is deprecated and under removal procedure.
90
+ * @property {boolean} [spa.autoStart] - If true, the agent will automatically start the single page application feature. Otherwise, it will be in a deferred state until the `start` API method is called.
91
+ * @property {boolean} [ssl] - If explicitly false, the agent will use HTTP instead of HTTPS. This setting should NOT be used.
92
+ * @property {Object} [user_actions]
93
+ * @property {boolean} [user_actions.enabled] - Must be true to allow UserAction events to be captured.
94
+ * @property {Array<string>} [user_actions.elementAttributes] - List of HTML Element properties to be captured with UserAction events' target elements. This may help to identify the source element being interacted with in the UI.
95
+ */
96
+ var _default = exports.default = {};
@@ -18,88 +18,14 @@ var _configurable = require("./configurable");
18
18
  */
19
19
 
20
20
  /**
21
- * @typedef {Object} Init
22
- * @property {Object} [ajax]
23
- * @property {Array<string>} [ajax.deny_list] - List of domain URLs to be excluded from AjaxRequest collection.
24
- * @property {boolean} [ajax.block_internal] - If true, agent requests going to harvest endpoint are treated as on deny list. In other words, agent will not self-report AJAX.
25
- * @property {boolean} [ajax.enabled] - Turn on/off the ajax feature (on by default).
26
- * @property {boolean} [ajax.autoStart] - If true, the agent will automatically start the ajax feature. Otherwise, it will be in a deferred state until the `start` API method is called.
27
- * @property {Object} [distributed_tracing]
28
- * @property {boolean} [distributed_tracing.enabled] - If true, distributed tracing headers will be added to outgoing requests. Requires ajax feature to be running.
29
- * @property {boolean} [distributed_tracing.exclude_newrelic_header]
30
- * @property {boolean} [distributed_tracing.cors_use_newrelic_header]
31
- * @property {boolean} [distributed_tracing.cors_use_tracecontext_headers]
32
- * @property {Array<string>} [distributed_tracing.allowed_origins]
33
- * @property {Array<string>} [feature_flags] - An array of feature flags to enable experimental features.
34
- * @property {Object} [generic_events]
35
- * @property {boolean} [generic_events.enabled] - Turn on/off the generic events feature (on by default). This is required for `PageAction`, `UserAction`, and `BrowserPerformance` events.
36
- * @property {boolean} [generic_events.autoStart] - If true, the agent will automatically start the generic events feature. Otherwise, it will be in a deferred state until the `start` API method is called.
37
- * @property {Object} [harvest]
38
- * @property {number} [harvest.interval] - The interval in seconds at which the agent will send out data. It's not recommended to change this value.
39
- * @property {Object} [jserrors]
40
- * @property {boolean} [jserrors.enabled] - Turn on/off the jserrors feature (on by default).
41
- * @property {boolean} [jserrors.autoStart] - If true, the agent will automatically start the jserrors feature. Otherwise, it will be in a deferred state until the `start` API method is called.
42
- * @property {Object} [logging]
43
- * @property {boolean} [logging.enabled] - Turn on/off the logging feature (on by default).
44
- * @property {boolean} [logging.autoStart] - If true, the agent will automatically start the logging feature. Otherwise, it will be in a deferred state until the `start` API method is called.
45
- * @property {Object} [metrics]
46
- * @property {boolean} [metrics.enabled] - Turn on/off the metrics feature (on by default).
47
- * @property {boolean} [metrics.autoStart] - If true, the agent will automatically start the metrics feature. Otherwise, it will be in a deferred state until the `start` API method is called.
48
- * @property {Array<Object>} [obfuscate] - Array of regexp and corresponding replacement patterns for obfuscating data.
49
- * @property {Object} [page_action]
50
- * @property {boolean} [page_action.enabled] - Must be true to allow PageAction events to be captured.
51
- * @property {Object} [page_view_event]
52
- * @property {boolean} [page_view_event.enabled] - This setting is ignored! PageViewEvent is always enabled by force.
53
- * @property {boolean} [page_view_event.autoStart] - If true, the agent will automatically send the RUM request. Otherwise, it will be in a deferred state until the `start` API method is called.
54
- * @property {Object} [page_view_timing]
55
- * @property {boolean} [page_view_timing.enabled] - Turn on/off the page view timing feature (on by default).
56
- * @property {boolean} [page_view_timing.autoStart] - If true, the agent will automatically start the page view timing feature. Otherwise, it will be in a deferred state until the `start` API method is called.
57
- * @property {Object} [performance]
58
- * @property {boolean} [performance.capture_marks] - If true, the agent will capture PerformanceMark events.
59
- * @property {boolean} [performance.capture_measures] - If true, the agent will capture PerformanceMeasure events.
60
- * @property {boolean} [performance.capture_detail] - If true, `BrowserPerformance` events from marks and measures will include, as attribute(s), the `detail` metadata provided to `markOptions` and `measureOptions`.
61
- * @property {Object} [performance.resources]
62
- * @property {boolean} [performance.resources.enabled] - If true, the agent will capture PerformanceResourceTiming entries.
63
- * @property {Array<string>} [performance.resources.asset_types] - Array of `initiatorType` strings to filter the desired ResourceTiming entries. By default, all resource types are captured.
64
- * @property {Array<string>} [performance.resources.first_party_domains] - Each resource URL will be checked against this list to determine if it should be labeled "first party" in the resulting `BrowserPerformance` event.
65
- * @property {boolean} [performance.resources.ignore_newrelic] - When true (default), resource entries associated with New Relic domains will be ignored.
66
- * @property {Object} [privacy]
67
- * @property {boolean} [privacy.cookies_enabled] - If true (default), session tracking of users across page loads is enabled in the agent. This is required for session trace, replay, and session-related features.
68
- * @property {Object} [proxy]
69
- * @property {string} [proxy.assets] - Set value will be used to overwrite the webpack asset path used to fetch agent assets.
70
- * @property {string} [proxy.beacon] - Set value will be used to overwrite the endpoint URL to which we send analytics.
71
- * @property {Object} [session]
72
- * @property {number} [session.expiresMs] - When session tracking is on, this determines how long a session will last before expiring. Modifying this value is not recommended.
73
- * @property {number} [session.inactiveMs] - When session tracking is on, this determines how long a session will last without user activity before expiring. Modifying this value is not recommended.
74
- * @property {Object} [session_replay]
75
- * @property {boolean} [session_replay.autoStart] - If true, the agent will automatically start the session replay feature. Otherwise, it will be in a deferred state until the `start` API method is called.
76
- * @property {boolean} [session_replay.enabled] - Turn on/off the session replay feature (off by default).
77
- * @property {boolean} [session_replay.preload] - If true, allow the agent to run rrweb recorder immediately instead of waiting until after the window.load event, for new sessions. Existing sessions ignore this setting.
78
- * @property {number} [session_replay.sampling_rate] - This setting is deprecated and ineffective. Sampling is controlled in New Relic by server-side configuration.
79
- * @property {number} [session_replay.error_sampling_rate] - This setting is deprecated and ineffective.
80
- * @property {boolean} [session_replay.collect_fonts] - When true, serialize fonts for collection without public asset url. This is currently broken -- https://github.com/rrweb-io/rrweb/issues/1304.
81
- * @property {boolean} [session_replay.inline_images] - When true, serialize images for collection without public asset url. Not recommended for use. This is currently for TESTING as it easily generates payloads too large to be harvested.
82
- * @property {boolean} [session_replay.fix_stylesheets] - When true, tries to fetch any missing stylesheets again to inline in replayer.
83
- * @property {boolean} [session_replay.mask_all_inputs] - If true, all input content will be masked with asterisks.
84
- * @property {string} [session_replay.mask_text_selector] - Set value should be in CSS selector syntax and is used to identify matching elements to mask.
85
- * @property {string} [session_replay.block_selector] - Set value should be in CSS selector syntax and is used to identify matching elements to block.
86
- * @property {Object} [session_replay.mask_input_options] - If mask_all_inputs is not true, this object will be used to select what input to mask. Passwords are forcibly always masked.
87
- * @property {Object} [session_trace]
88
- * @property {boolean} [session_trace.enabled] - Turn on/off the session trace feature (on by default).
89
- * @property {boolean} [session_trace.autoStart] - If true, the agent will automatically start the session trace feature. Otherwise, it will be in a deferred state until the `start` API method is called.
90
- * @property {Object} [soft_navigations]
91
- * @property {boolean} [soft_navigations.enabled] - Turn on/off the soft navigations feature (on by default).
92
- * @property {boolean} [soft_navigations.autoStart] - If true, the agent will automatically start the soft navigations feature. Otherwise, it will be in a deferred state until the `start` API method is called.
93
- * @property {Object} [spa]
94
- * @property {boolean} [spa.enabled] - Turn on/off the single page application feature (on by default). NOTE: the SPA feature is deprecated and under removal procedure.
95
- * @property {boolean} [spa.autoStart] - If true, the agent will automatically start the single page application feature. Otherwise, it will be in a deferred state until the `start` API method is called.
96
- * @property {boolean} [ssl] - If explicitly false, the agent will use HTTP instead of HTTPS. This setting should NOT be used.
97
- * @property {Object} [user_actions]
98
- * @property {boolean} [user_actions.enabled] - Must be true to allow UserAction events to be captured.
99
- * @property {Array<string>} [user_actions.elementAttributes] - List of HTML Element properties to be captured with UserAction events' target elements. This may help to identify the source element being interacted with in the UI.
21
+ * @typedef {import('./init-types').Init} Init
100
22
  */
101
23
 
102
24
  const nrMask = '[data-nr-mask]';
25
+
26
+ /**
27
+ * @returns {Init} the default configuration object
28
+ */
103
29
  const model = () => {
104
30
  const hiddenState = {
105
31
  feature_flags: [],
@@ -137,6 +63,10 @@ const model = () => {
137
63
  enabled: true,
138
64
  autoStart: true
139
65
  },
66
+ api: {
67
+ allow_registered_children: true,
68
+ duplicate_registered_data: false
69
+ },
140
70
  distributed_tracing: {
141
71
  enabled: undefined,
142
72
  exclude_newrelic_header: undefined,
@@ -26,21 +26,22 @@ const readonly = {
26
26
  originTime: _runtime.originTime
27
27
  };
28
28
  const model = {
29
+ /** Agent-specific metadata found in the RUM call response. ex. entityGuid */
30
+ appMetadata: {},
29
31
  customTransaction: undefined,
32
+ denyList: undefined,
30
33
  disabled: false,
34
+ entityManager: undefined,
35
+ harvester: undefined,
31
36
  isolatedBacklog: false,
32
37
  loaderType: undefined,
33
38
  maxBytes: 30000,
39
+ obfuscator: undefined,
34
40
  onerror: undefined,
35
41
  ptid: undefined,
36
42
  releaseIds: {},
37
- /** Agent-specific metadata found in the RUM call response. ex. entityGuid */
38
- appMetadata: {},
39
43
  session: undefined,
40
- denyList: undefined,
41
- timeKeeper: undefined,
42
- obfuscator: undefined,
43
- harvester: undefined
44
+ timeKeeper: undefined
44
45
  };
45
46
  const _cache = {};
46
47
  function getRuntime(id) {
@@ -17,7 +17,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.DIST_METHOD = exports.BUILD_EN
17
17
  /**
18
18
  * Exposes the version of the agent
19
19
  */
20
- const VERSION = exports.VERSION = "1.286.0";
20
+ const VERSION = exports.VERSION = "1.288.0";
21
21
 
22
22
  /**
23
23
  * Exposes the build type of the agent
@@ -17,7 +17,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.DIST_METHOD = exports.BUILD_EN
17
17
  /**
18
18
  * Exposes the version of the agent
19
19
  */
20
- const VERSION = exports.VERSION = "1.286.0";
20
+ const VERSION = exports.VERSION = "1.288.0";
21
21
 
22
22
  /**
23
23
  * Exposes the build type of the agent
@@ -152,7 +152,7 @@ function send(agentRef, {
152
152
  const protocol = agentRef.init.ssl === false ? 'http' : 'https';
153
153
  const perceivedBeacon = agentRef.init.proxy.beacon || agentRef.info.errorBeacon;
154
154
  const url = raw ? "".concat(protocol, "://").concat(perceivedBeacon, "/").concat(endpoint) : "".concat(protocol, "://").concat(perceivedBeacon).concat(endpoint !== _features.RUM ? '/' + endpoint : '', "/1/").concat(targetApp.licenseKey);
155
- const baseParams = !raw ? baseQueryString(agentRef, qs, endpoint, targetApp.appId) : '';
155
+ const baseParams = !raw ? baseQueryString(agentRef, qs, endpoint, targetApp.applicationID) : '';
156
156
  let payloadParams = (0, _encode.obj)(qs, agentRef.runtime.maxBytes);
157
157
  if (baseParams === '' && payloadParams.startsWith('&')) {
158
158
  payloadParams = payloadParams.substring(1);
@@ -192,8 +192,8 @@ function send(agentRef, {
192
192
  sent: this.status !== 0,
193
193
  status: this.status,
194
194
  retry: shouldRetry(this.status),
195
- xhr: this,
196
195
  fullUrl,
196
+ xhr: this,
197
197
  targetApp
198
198
  };
199
199
  if (localOpts.needResponse) cbResult.responseText = this.responseText;
@@ -38,7 +38,8 @@ const model = {
38
38
  loggingMode: _constants3.LOGGING_MODE.OFF,
39
39
  serverTimeDiff: null,
40
40
  // set by TimeKeeper; "undefined" value will not be stringified and stored but "null" will
41
- custom: {}
41
+ custom: {},
42
+ numOfResets: 0
42
43
  };
43
44
  class SessionEntity {
44
45
  /**
@@ -84,7 +85,8 @@ class SessionEntity {
84
85
  setup({
85
86
  value = (0, _uniqueId.generateRandomHexString)(16),
86
87
  expiresMs = _constants.DEFAULT_EXPIRES_MS,
87
- inactiveMs = _constants.DEFAULT_INACTIVE_MS
88
+ inactiveMs = _constants.DEFAULT_INACTIVE_MS,
89
+ numOfResets = 0
88
90
  }) {
89
91
  /** Ensure that certain properties are preserved across a reset if already set */
90
92
  const persistentAttributes = {
@@ -113,6 +115,7 @@ class SessionEntity {
113
115
  // this gets ignored if the value is falsy, allowing for session entities that do not expire
114
116
  if (expiresMs) {
115
117
  this.state.expiresAt = initialRead?.expiresAt || this.getFutureTimestamp(expiresMs);
118
+ this.state.numOfResets = initialRead?.numOfResets || numOfResets;
116
119
  this.expiresTimer = new _timer.Timer({
117
120
  // When the inactive timer ends, collect a SM and reset the session
118
121
  onEnd: () => {
@@ -247,7 +250,8 @@ class SessionEntity {
247
250
  key: this.key,
248
251
  storage: this.storage,
249
252
  expiresMs: this.expiresMs,
250
- inactiveMs: this.inactiveMs
253
+ inactiveMs: this.inactiveMs,
254
+ numOfResets: ++this.state.numOfResets
251
255
  });
252
256
  return this.read();
253
257
  } catch (e) {
@@ -266,6 +270,9 @@ class SessionEntity {
266
270
  inactiveAt: this.getFutureTimestamp(this.inactiveMs)
267
271
  });
268
272
  }
273
+ isAfterSessionExpiry(timestamp) {
274
+ return this.state.numOfResets > 0 || typeof timestamp === 'number' && typeof this.state.expiresAt === 'number' && timestamp >= this.state.expiresAt;
275
+ }
269
276
 
270
277
  /**
271
278
  * @param {number} timestamp
@@ -5,7 +5,6 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.activateFeatures = activateFeatures;
7
7
  exports.activatedFeatures = void 0;
8
- var _contextualEe = require("../event-emitter/contextual-ee");
9
8
  var _globalEvent = require("../dispatch/global-event");
10
9
  /**
11
10
  * Copyright 2020-2025 New Relic, Inc. All rights reserved.
@@ -24,12 +23,12 @@ const activatedFeatures = exports.activatedFeatures = {};
24
23
  * @param {string} agentIdentifier agent instance identifier
25
24
  * @returns {void}
26
25
  */
27
- function activateFeatures(flags, agentIdentifier) {
28
- const sharedEE = _contextualEe.ee.get(agentIdentifier);
26
+ function activateFeatures(flags, agentRef) {
27
+ const agentIdentifier = agentRef.agentIdentifier;
29
28
  activatedFeatures[agentIdentifier] ??= {};
30
- if (!(flags && typeof flags === 'object')) return;
29
+ if (!flags || typeof flags !== 'object') return;
31
30
  if (sentIds.has(agentIdentifier)) return;
32
- sharedEE.emit('rumresp', [flags]);
31
+ agentRef.ee.emit('rumresp', [flags]);
33
32
  activatedFeatures[agentIdentifier] = flags;
34
33
  sentIds.add(agentIdentifier);
35
34
 
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isContainerAgentTarget = isContainerAgentTarget;
7
+ exports.isValidTarget = isValidTarget;
8
+ /**
9
+ * Copyright 2020-2025 New Relic, Inc. All rights reserved.
10
+ * SPDX-License-Identifier: Apache-2.0
11
+ */
12
+
13
+ /**
14
+ * @param {Object} [target] - the target to be validated
15
+ * @param {boolean} [allowUndefined=true]
16
+ * @returns {boolean}
17
+ */
18
+ function isValidTarget(target) {
19
+ /** target can be undefined to support legacy/default behaviors - main agent does not supply a target */
20
+ if (!target) return true;
21
+ /** if not undefined, we require specific values */
22
+ return !!(target.licenseKey && target.applicationID);
23
+ }
24
+
25
+ /**
26
+ * Checks if the target matches the container agent target
27
+ * @param {*} target the target to be validated
28
+ * @param {*} agentRef the agent reference to be validated
29
+ * @returns {boolean}
30
+ */
31
+ function isContainerAgentTarget(target, agentRef) {
32
+ if (!target) return true;
33
+ return target.licenseKey === agentRef.info.licenseKey && target.applicationID === agentRef.info.applicationID;
34
+ }
@@ -61,7 +61,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
61
61
 
62
62
  // Report ajax timeslice metric (to be harvested by jserrors feature, but only if it's running).
63
63
  if (jserrorsInUse && (shouldCollect || !shouldOmitAjaxMetrics)) {
64
- this.agentRef.sharedAggregator.add(['xhr', hash, params, metrics]);
64
+ this.agentRef.sharedAggregator?.add(['xhr', hash, params, metrics]);
65
65
  }
66
66
  if (!shouldCollect) {
67
67
  if (params.hostname === this.agentRef.info.errorBeacon || this.agentRef.init.proxy?.beacon && params.hostname === this.agentRef.init.proxy.beacon) {
@@ -114,6 +114,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
114
114
  }
115
115
  }
116
116
  serializer(eventBuffer) {
117
+ if (!eventBuffer.length) return;
117
118
  const addString = (0, _belSerializer.getAddStringContext)(this.agentIdentifier);
118
119
  let payload = 'bel.7;';
119
120
  for (let i = 0; i < eventBuffer.length; i++) {
@@ -44,7 +44,8 @@ class Aggregate extends _aggregateBase.AggregateBase {
44
44
  });
45
45
  }, this.featureName, this.ee);
46
46
  if (agentRef.init.page_action.enabled) {
47
- (0, _registerHandler.registerHandler)('api-addPageAction', (timestamp, name, attributes) => {
47
+ (0, _registerHandler.registerHandler)('api-addPageAction', (timestamp, name, attributes, targetEntityGuid) => {
48
+ if (!this.agentRef.runtime.entityManager.get(targetEntityGuid)) return (0, _console.warn)(56, this.featureName);
48
49
  this.addEvent({
49
50
  ...attributes,
50
51
  eventType: 'PageAction',
@@ -56,7 +57,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
56
57
  browserWidth: window.document.documentElement?.clientWidth,
57
58
  browserHeight: window.document.documentElement?.clientHeight
58
59
  })
59
- });
60
+ }, targetEntityGuid);
60
61
  }, this.featureName, this.ee);
61
62
  }
62
63
  let addUserAction = () => {/** no-op */};
@@ -238,9 +239,10 @@ class Aggregate extends _aggregateBase.AggregateBase {
238
239
  * * sessionTraceId: set by the `ptid=` query param
239
240
  * * userAgent*: set by the userAgent header
240
241
  * @param {object=} obj the event object for storing in the event buffer
242
+ * @param {string=} targetEntityGuid the target entity guid for the event to scope buffering and harvesting. Defaults to agent config if undefined
241
243
  * @returns void
242
244
  */
243
- addEvent(obj = {}) {
245
+ addEvent(obj = {}, targetEntityGuid) {
244
246
  if (!obj || !Object.keys(obj).length) return;
245
247
  if (!obj.eventType) {
246
248
  (0, _console.warn)(44);
@@ -265,14 +267,16 @@ class Aggregate extends _aggregateBase.AggregateBase {
265
267
  /** Event-specific attributes take precedence over agent-level custom attributes and fallbacks */
266
268
  ...obj
267
269
  };
268
- const addedEvent = this.events.add(eventAttributes);
269
- if (!addedEvent && !this.events.isEmpty()) {
270
+ const addedEvent = this.events.add(eventAttributes, targetEntityGuid);
271
+ if (!addedEvent && !this.events.isEmpty(undefined, targetEntityGuid)) {
270
272
  /** could not add the event because it pushed the buffer over the limit
271
273
  * so we harvest early, and try to add it again now that the buffer is cleared
272
274
  * if it fails again, we do nothing
273
275
  */
274
276
  this.ee.emit(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['GenericEvents/Harvest/Max/Seen']);
275
- this.agentRef.runtime.harvester.triggerHarvestFor(this);
277
+ this.agentRef.runtime.harvester.triggerHarvestFor(this, {
278
+ targetEntityGuid
279
+ });
276
280
  this.events.add(eventAttributes);
277
281
  }
278
282
  }
@@ -18,6 +18,8 @@ var _aggregateBase = require("../../utils/aggregate-base");
18
18
  var _now = require("../../../common/timing/now");
19
19
  var _traverse = require("../../../common/util/traverse");
20
20
  var _internalErrors = require("./internal-errors");
21
+ var _target = require("../../../common/util/target");
22
+ var _console = require("../../../common/util/console");
21
23
  /**
22
24
  * Copyright 2020-2025 New Relic, Inc. All rights reserved.
23
25
  * SPDX-License-Identifier: Apache-2.0
@@ -101,10 +103,13 @@ class Aggregate extends _aggregateBase.AggregateBase {
101
103
  * @param {object=} customAttributes any custom attributes to be included in the error payload
102
104
  * @param {boolean=} hasReplay a flag indicating if the error occurred during a replay session
103
105
  * @param {string=} swallowReason a string indicating pre-defined reason if swallowing the error. Mainly used by the internal error SMs.
106
+ * @param {object=} target the target to buffer and harvest to, if undefined the default configuration target is used
104
107
  * @returns
105
108
  */
106
- storeError(err, time, internal, customAttributes, hasReplay, swallowReason) {
109
+ storeError(err, time, internal, customAttributes, hasReplay, swallowReason, targetEntityGuid) {
107
110
  if (!err) return;
111
+ const target = this.agentRef.runtime.entityManager.get(targetEntityGuid);
112
+ if (!target) return (0, _console.warn)(56, this.featureName);
108
113
  // are we in an interaction
109
114
  time = time || (0, _now.now)();
110
115
  let filterOutput;
@@ -136,7 +141,9 @@ class Aggregate extends _aggregateBase.AggregateBase {
136
141
  // Notice if filterOutput isn't false|undefined OR our specified object, this func would've returned already (so it's unnecessary to req-check group).
137
142
  // Do not modify the name ('errorGroup') of params without DEM approval!
138
143
  if (filterOutput?.group) params.errorGroup = filterOutput.group;
139
- if (hasReplay) params.hasReplay = hasReplay;
144
+
145
+ // Should only decorate "hasReplay" for the container agent, so check if the target matches the config
146
+ if (hasReplay && (0, _target.isContainerAgentTarget)(target, this.agentRef)) params.hasReplay = hasReplay;
140
147
  /**
141
148
  * The bucketHash is different from the params.stackHash because the params.stackHash is based on the canonicalized
142
149
  * stack trace and is used downstream in NR1 to attempt to group the same errors across different browsers. However,
@@ -171,33 +178,38 @@ class Aggregate extends _aggregateBase.AggregateBase {
171
178
 
172
179
  // Trace sends the error in its payload, and both trace & replay simply listens for any error to occur.
173
180
  const jsErrorEvent = [type, bucketHash, params, newMetrics, customAttributes];
174
- (0, _handle.handle)('trace-jserror', jsErrorEvent, undefined, _features.FEATURE_NAMES.sessionTrace, this.ee);
181
+ if (this.shouldAllowMainAgentToCapture(targetEntityGuid)) (0, _handle.handle)('trace-jserror', jsErrorEvent, undefined, _features.FEATURE_NAMES.sessionTrace, this.ee);
175
182
  // still send EE events for other features such as above, but stop this one from aggregating internal data
176
183
  if (this.blocked) return;
177
184
  if (err?.__newrelic?.[this.agentIdentifier]) {
178
185
  params._interactionId = err.__newrelic[this.agentIdentifier].interactionId;
179
186
  params._interactionNodeId = err.__newrelic[this.agentIdentifier].interactionNodeId;
180
187
  }
181
- const softNavInUse = Boolean(this.agentRef.features?.[_features.FEATURE_NAMES.softNav]);
182
- // Note: the following are subject to potential race cond wherein if the other feature aren't fully initialized, it'll be treated as there being no associated interaction.
183
- // They each will also tack on their respective properties to the params object as part of the decision flow.
184
- if (softNavInUse) (0, _handle.handle)('jserror', [params, time], undefined, _features.FEATURE_NAMES.softNav, this.ee);else (0, _handle.handle)('spa-jserror', jsErrorEvent, undefined, _features.FEATURE_NAMES.spa, this.ee);
185
- if (params.browserInteractionId && !params._softNavFinished) {
186
- // hold onto the error until the in-progress interaction is done, eithered saved or discarded
187
- this.bufferedErrorsUnderSpa[params.browserInteractionId] ??= [];
188
- this.bufferedErrorsUnderSpa[params.browserInteractionId].push(jsErrorEvent);
189
- } else if (params._interactionId != null) {
190
- // same as above, except tailored for the way old spa does it
191
- this.bufferedErrorsUnderSpa[params._interactionId] = this.bufferedErrorsUnderSpa[params._interactionId] || [];
192
- this.bufferedErrorsUnderSpa[params._interactionId].push(jsErrorEvent);
193
- } else {
194
- // Either there is no interaction (then all these params properties will be undefined) OR there's a related soft navigation that's already completed.
195
- // The old spa does not look up completed interactions at all, so there's no need to consider it.
196
- this.#storeJserrorForHarvest(jsErrorEvent, params.browserInteractionId !== undefined, params._softNavAttributes);
188
+ if (this.shouldAllowMainAgentToCapture(targetEntityGuid)) {
189
+ const softNavInUse = Boolean(this.agentRef.features?.[_features.FEATURE_NAMES.softNav]);
190
+ // Note: the following are subject to potential race cond wherein if the other feature aren't fully initialized, it'll be treated as there being no associated interaction.
191
+ // They each will also tack on their respective properties to the params object as part of the decision flow.
192
+ if (softNavInUse) (0, _handle.handle)('jserror', [params, time], undefined, _features.FEATURE_NAMES.softNav, this.ee);else (0, _handle.handle)('spa-jserror', jsErrorEvent, undefined, _features.FEATURE_NAMES.spa, this.ee);
193
+ if (params.browserInteractionId && !params._softNavFinished) {
194
+ // hold onto the error until the in-progress interaction is done, eithered saved or discarded
195
+ this.bufferedErrorsUnderSpa[params.browserInteractionId] ??= [];
196
+ this.bufferedErrorsUnderSpa[params.browserInteractionId].push(jsErrorEvent);
197
+ } else if (params._interactionId != null) {
198
+ // same as above, except tailored for the way old spa does it
199
+ this.bufferedErrorsUnderSpa[params._interactionId] = this.bufferedErrorsUnderSpa[params._interactionId] || [];
200
+ this.bufferedErrorsUnderSpa[params._interactionId].push(jsErrorEvent);
201
+ } else {
202
+ // Either there is no interaction (then all these params properties will be undefined) OR there's a related soft navigation that's already completed.
203
+ // The old spa does not look up completed interactions at all, so there's no need to consider it.
204
+ this.#storeJserrorForHarvest(jsErrorEvent, params.browserInteractionId !== undefined, params._softNavAttributes);
205
+ }
197
206
  }
207
+
208
+ // always add directly if scoped to a sub-entity, the other pathways above will be deterministic if the main agent should procede
209
+ if (targetEntityGuid) this.#storeJserrorForHarvest([...jsErrorEvent, targetEntityGuid], false, params._softNavAttributes);
198
210
  }
199
211
  #storeJserrorForHarvest(errorInfoArr, softNavOccurredFinished, softNavCustomAttrs = {}) {
200
- let [type, bucketHash, params, newMetrics, localAttrs] = errorInfoArr;
212
+ let [type, bucketHash, params, newMetrics, localAttrs, targetEntityGuid] = errorInfoArr;
201
213
  const allCustomAttrs = {};
202
214
  if (softNavOccurredFinished) {
203
215
  Object.entries(softNavCustomAttrs).forEach(([k, v]) => setCustom(k, v)); // when an ixn finishes, it'll include stuff in jsAttributes + attrs specific to the ixn
@@ -213,12 +225,22 @@ class Aggregate extends _aggregateBase.AggregateBase {
213
225
 
214
226
  const jsAttributesHash = (0, _stringHashCode.stringHashCode)((0, _stringify.stringify)(allCustomAttrs));
215
227
  const aggregateHash = bucketHash + ':' + jsAttributesHash;
216
- this.events.add([type, aggregateHash, params, newMetrics, allCustomAttrs]);
228
+ this.events.add([type, aggregateHash, params, newMetrics, allCustomAttrs], targetEntityGuid);
217
229
  function setCustom(key, val) {
218
230
  allCustomAttrs[key] = val && typeof val === 'object' ? (0, _stringify.stringify)(val) : val;
219
231
  }
220
232
  }
221
233
 
234
+ /**
235
+ * If the event lacks an entityGuid (the default behavior), the main agent should capture the data. If the data is assigned to a sub-entity target
236
+ * the main agent should not capture events unless it is configured to do so.
237
+ * @param {string} entityGuid - the context object for the event
238
+ * @returns {boolean} - whether the main agent should capture the event to its internal target
239
+ */
240
+ shouldAllowMainAgentToCapture(entityGuid) {
241
+ return !entityGuid || this.agentRef.init.api.duplicate_registered_data;
242
+ }
243
+
222
244
  // TO-DO: Remove this function when old spa is taken out. #storeJserrorForHarvest handles the work with the softnav feature.
223
245
  onInteractionDone(interaction, wasSaved) {
224
246
  if (!this.bufferedErrorsUnderSpa[interaction.id] || this.blocked) return;
@@ -237,7 +259,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
237
259
  var hash = wasSaved ? item[1] + interaction.root.attrs.id : item[1];
238
260
  var jsAttributesHash = (0, _stringHashCode.stringHashCode)((0, _stringify.stringify)(allCustomAttrs));
239
261
  var aggregateHash = hash + ':' + jsAttributesHash;
240
- this.events.add([item[0], aggregateHash, params, item[3], allCustomAttrs]);
262
+ this.events.add([item[0], aggregateHash, params, item[3], allCustomAttrs], item[5]);
241
263
  function setCustom([key, val]) {
242
264
  allCustomAttrs[key] = val && typeof val === 'object' ? (0, _stringify.stringify)(val) : val;
243
265
  }