@agent-native/core 0.98.4 → 0.98.6

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 (314) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +28 -0
  3. package/corpus/core/docs/content/durable-background-runs.mdx +37 -0
  4. package/corpus/core/docs/content/external-agents.mdx +62 -7
  5. package/corpus/core/docs/content/locales/ar-SA/external-agents.mdx +38 -7
  6. package/corpus/core/docs/content/locales/ar-SA/tracking.mdx +2 -0
  7. package/corpus/core/docs/content/locales/de-DE/external-agents.mdx +39 -7
  8. package/corpus/core/docs/content/locales/de-DE/tracking.mdx +2 -0
  9. package/corpus/core/docs/content/locales/es-ES/external-agents.mdx +39 -7
  10. package/corpus/core/docs/content/locales/es-ES/tracking.mdx +2 -0
  11. package/corpus/core/docs/content/locales/fr-FR/external-agents.mdx +39 -7
  12. package/corpus/core/docs/content/locales/fr-FR/tracking.mdx +4 -2
  13. package/corpus/core/docs/content/locales/hi-IN/external-agents.mdx +38 -7
  14. package/corpus/core/docs/content/locales/hi-IN/tracking.mdx +2 -0
  15. package/corpus/core/docs/content/locales/ja-JP/external-agents.mdx +38 -7
  16. package/corpus/core/docs/content/locales/ja-JP/tracking.mdx +2 -0
  17. package/corpus/core/docs/content/locales/ko-KR/external-agents.mdx +38 -7
  18. package/corpus/core/docs/content/locales/ko-KR/tracking.mdx +2 -0
  19. package/corpus/core/docs/content/locales/pt-BR/external-agents.mdx +39 -7
  20. package/corpus/core/docs/content/locales/pt-BR/tracking.mdx +2 -0
  21. package/corpus/core/docs/content/locales/zh-CN/external-agents.mdx +37 -7
  22. package/corpus/core/docs/content/locales/zh-CN/tracking.mdx +2 -0
  23. package/corpus/core/docs/content/locales/zh-TW/durable-background-runs.mdx +14 -0
  24. package/corpus/core/docs/content/locales/zh-TW/external-agents.mdx +37 -7
  25. package/corpus/core/docs/content/locales/zh-TW/tracking.mdx +2 -0
  26. package/corpus/core/docs/content/tracking.mdx +2 -0
  27. package/corpus/core/package.json +1 -1
  28. package/corpus/core/src/a2a/handlers.ts +95 -21
  29. package/corpus/core/src/a2a/task-store.ts +65 -3
  30. package/corpus/core/src/agent/durable-background.ts +16 -16
  31. package/corpus/core/src/agent/engine/ai-sdk-engine.ts +25 -8
  32. package/corpus/core/src/agent/engine/anthropic-engine.ts +17 -3
  33. package/corpus/core/src/agent/engine/output-tokens.ts +6 -6
  34. package/corpus/core/src/agent/production-agent.ts +200 -27
  35. package/corpus/core/src/agent/run-manager.ts +81 -1
  36. package/corpus/core/src/agent/run-store.ts +301 -41
  37. package/corpus/core/src/client/AgentPanel.tsx +6 -2
  38. package/corpus/core/src/client/AssistantChat.tsx +364 -69
  39. package/corpus/core/src/client/agent-chat-adapter.ts +169 -1
  40. package/corpus/core/src/client/chat/message-components.tsx +3 -0
  41. package/corpus/core/src/client/chat/tool-call-display.tsx +20 -36
  42. package/corpus/core/src/client/conversation/use-near-bottom-autoscroll.ts +7 -0
  43. package/corpus/core/src/client/extensions/AgentNativeExtensionFrame.tsx +2 -0
  44. package/corpus/core/src/client/extensions/EmbeddedExtension.tsx +2 -0
  45. package/corpus/core/src/client/extensions/ExtensionEditor.tsx +9 -2
  46. package/corpus/core/src/client/extensions/ExtensionViewer.tsx +2 -0
  47. package/corpus/core/src/client/extensions/InlineExtensionFrame.tsx +2 -0
  48. package/corpus/core/src/client/extensions/portable-extension.ts +2 -0
  49. package/corpus/core/src/client/session-replay.ts +361 -29
  50. package/corpus/core/src/client/sse-event-processor.ts +43 -1
  51. package/corpus/core/src/demo/actions/toggle-demo-mode.ts +1 -1
  52. package/corpus/core/src/demo/config.ts +6 -6
  53. package/corpus/core/src/demo/fetch-interceptor.ts +13 -4
  54. package/corpus/core/src/demo/redact.ts +13 -149
  55. package/corpus/core/src/extensions/html-shell.ts +3 -0
  56. package/corpus/core/src/extensions/session-replay-iframe.ts +131 -0
  57. package/corpus/core/src/integrations/adapters/slack.ts +123 -13
  58. package/corpus/core/src/integrations/identity-links-store.ts +210 -0
  59. package/corpus/core/src/integrations/identity.ts +132 -0
  60. package/corpus/core/src/integrations/index.ts +6 -0
  61. package/corpus/core/src/integrations/plugin.ts +58 -1
  62. package/corpus/core/src/integrations/types.ts +7 -0
  63. package/corpus/core/src/mcp/build-server.ts +127 -22
  64. package/corpus/core/src/mcp/external-agent-policy.ts +18 -0
  65. package/corpus/core/src/mcp/index.ts +1 -0
  66. package/corpus/core/src/scripts/agent-engines/list-agent-engines.ts +1 -20
  67. package/corpus/core/src/server/agent-chat/plugin-options.ts +12 -1
  68. package/corpus/core/src/server/agent-chat/script-entries.ts +20 -3
  69. package/corpus/core/src/server/agent-chat-plugin.ts +3 -0
  70. package/corpus/core/src/session-replay-iframe-protocol.ts +58 -0
  71. package/corpus/core/src/shared/reasoning-effort.ts +35 -0
  72. package/corpus/core/src/styles/agent-conversation.css +26 -0
  73. package/corpus/core/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +34 -5
  74. package/corpus/core/src/templates/workspace-core/.agents/skills/observability/SKILL.md +0 -15
  75. package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +30 -21
  76. package/corpus/templates/analytics/AGENTS.md +27 -0
  77. package/corpus/templates/analytics/actions/create-session-replay-agent-link.ts +0 -1
  78. package/corpus/templates/analytics/actions/get-error-issue.ts +1 -0
  79. package/corpus/templates/analytics/actions/get-session-replay-summary.ts +1 -0
  80. package/corpus/templates/analytics/actions/get-session-replay-timeline.ts +40 -0
  81. package/corpus/templates/analytics/actions/list-error-issues.ts +13 -0
  82. package/corpus/templates/analytics/actions/list-session-recordings.ts +1 -0
  83. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +4 -0
  84. package/corpus/templates/analytics/app/global.css +2 -2
  85. package/corpus/templates/analytics/app/hooks/use-dashboard-chat-context.ts +41 -4
  86. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +52 -203
  87. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +69 -16
  88. package/corpus/templates/analytics/changelog/2026-07-12-analytics-chat-retries-before-showing-a-generic-no-data-mess.md +6 -0
  89. package/corpus/templates/analytics/changelog/2026-07-12-analytics-sessions-search-no-longer-loses-fast-keystrokes-an.md +6 -0
  90. package/corpus/templates/analytics/changelog/2026-07-12-chart-selection-respects-chat-state.md +6 -0
  91. package/corpus/templates/analytics/changelog/2026-07-12-connected-external-agents-can-now-look-up-sessions-error-iss.md +6 -0
  92. package/corpus/templates/analytics/changelog/2026-07-12-demo-mode-anonymizes-error-reporting-emails.md +6 -0
  93. package/corpus/templates/analytics/changelog/2026-07-12-session-identities-stay-visible-when-demo-mode-is-off.md +6 -0
  94. package/corpus/templates/analytics/changelog/2026-07-12-session-replays-show-iframe-content.md +6 -0
  95. package/corpus/templates/analytics/netlify.toml +0 -3
  96. package/corpus/templates/analytics/server/lib/analytics-connector-catalog.ts +14 -0
  97. package/corpus/templates/analytics/server/lib/error-capture.ts +101 -2
  98. package/corpus/templates/analytics/server/lib/real-data-actions.ts +24 -0
  99. package/corpus/templates/analytics/server/lib/session-replay-agent-context.ts +49 -17
  100. package/corpus/templates/analytics/server/lib/session-replay.ts +18 -16
  101. package/corpus/templates/analytics/server/plugins/agent-chat.ts +43 -6
  102. package/corpus/templates/analytics/server/plugins/db.ts +15 -0
  103. package/corpus/templates/assets/app/global.css +1 -1
  104. package/corpus/templates/brain/app/global.css +2 -2
  105. package/corpus/templates/brain/changelog/2026-07-12-fix-long-response-progress.md +6 -0
  106. package/corpus/templates/forms/app/components/CloudUpgrade.tsx +1 -1
  107. package/corpus/templates/forms/app/components/ThemeToggle.tsx +22 -6
  108. package/corpus/templates/forms/app/components/builder/FieldPropertiesPanel.tsx +5 -5
  109. package/corpus/templates/forms/app/components/builder/FieldRenderer.tsx +3 -3
  110. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +16 -16
  111. package/corpus/templates/forms/app/global.css +164 -13
  112. package/corpus/templates/forms/app/pages/AskPage.tsx +35 -13
  113. package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +143 -67
  114. package/corpus/templates/forms/app/pages/FormFillPage.tsx +44 -11
  115. package/corpus/templates/forms/app/pages/FormsListPage.tsx +42 -24
  116. package/corpus/templates/forms/app/pages/ResponseInsightsPage.tsx +28 -15
  117. package/corpus/templates/forms/app/pages/ResponsesPage.tsx +46 -20
  118. package/corpus/templates/forms/app/routes/_app.settings.tsx +1 -1
  119. package/corpus/templates/forms/changelog/2026-07-12-ask-forms-suggestions-now-sit-beneath-the-composer-for-a-tig.md +6 -0
  120. package/corpus/templates/forms/changelog/2026-07-12-builder-response-tables-now-fill-the-view-without-a-redundan.md +6 -0
  121. package/corpus/templates/forms/changelog/2026-07-12-form-builder-surfaces-are-calmer-fields-stay-stable-on-hover.md +6 -0
  122. package/corpus/templates/forms/changelog/2026-07-12-response-tables-now-fill-the-available-pane-with-a-flexible-.md +6 -0
  123. package/corpus/templates/forms/changelog/2026-07-12-smoother-more-tactile-controls-throughout-animated-icon-and-.md +6 -0
  124. package/corpus/templates/mail/AGENTS.md +3 -1
  125. package/corpus/templates/mail/app/components/email/EmailThread.tsx +21 -13
  126. package/corpus/templates/mail/app/components/email/email-iframe-document.ts +18 -0
  127. package/corpus/templates/mail/server/lib/mail-integrations.ts +3 -0
  128. package/dist/a2a/handlers.d.ts.map +1 -1
  129. package/dist/a2a/handlers.js +84 -15
  130. package/dist/a2a/handlers.js.map +1 -1
  131. package/dist/a2a/task-store.d.ts +20 -1
  132. package/dist/a2a/task-store.d.ts.map +1 -1
  133. package/dist/a2a/task-store.js +57 -4
  134. package/dist/a2a/task-store.js.map +1 -1
  135. package/dist/agent/durable-background.d.ts +10 -10
  136. package/dist/agent/durable-background.d.ts.map +1 -1
  137. package/dist/agent/durable-background.js +16 -16
  138. package/dist/agent/durable-background.js.map +1 -1
  139. package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
  140. package/dist/agent/engine/ai-sdk-engine.js +19 -8
  141. package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
  142. package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
  143. package/dist/agent/engine/anthropic-engine.js +11 -3
  144. package/dist/agent/engine/anthropic-engine.js.map +1 -1
  145. package/dist/agent/engine/output-tokens.js +6 -6
  146. package/dist/agent/engine/output-tokens.js.map +1 -1
  147. package/dist/agent/production-agent.d.ts +52 -0
  148. package/dist/agent/production-agent.d.ts.map +1 -1
  149. package/dist/agent/production-agent.js +154 -26
  150. package/dist/agent/production-agent.js.map +1 -1
  151. package/dist/agent/run-manager.d.ts +9 -0
  152. package/dist/agent/run-manager.d.ts.map +1 -1
  153. package/dist/agent/run-manager.js +71 -1
  154. package/dist/agent/run-manager.js.map +1 -1
  155. package/dist/agent/run-store.d.ts +9 -0
  156. package/dist/agent/run-store.d.ts.map +1 -1
  157. package/dist/agent/run-store.js +243 -48
  158. package/dist/agent/run-store.js.map +1 -1
  159. package/dist/client/AgentPanel.d.ts.map +1 -1
  160. package/dist/client/AgentPanel.js +6 -2
  161. package/dist/client/AgentPanel.js.map +1 -1
  162. package/dist/client/AssistantChat.d.ts +21 -0
  163. package/dist/client/AssistantChat.d.ts.map +1 -1
  164. package/dist/client/AssistantChat.js +298 -67
  165. package/dist/client/AssistantChat.js.map +1 -1
  166. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  167. package/dist/client/agent-chat-adapter.js +146 -1
  168. package/dist/client/agent-chat-adapter.js.map +1 -1
  169. package/dist/client/chat/message-components.d.ts.map +1 -1
  170. package/dist/client/chat/message-components.js +2 -1
  171. package/dist/client/chat/message-components.js.map +1 -1
  172. package/dist/client/chat/tool-call-display.d.ts +3 -1
  173. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  174. package/dist/client/chat/tool-call-display.js +13 -37
  175. package/dist/client/chat/tool-call-display.js.map +1 -1
  176. package/dist/client/conversation/use-near-bottom-autoscroll.d.ts +1 -0
  177. package/dist/client/conversation/use-near-bottom-autoscroll.d.ts.map +1 -1
  178. package/dist/client/conversation/use-near-bottom-autoscroll.js +6 -0
  179. package/dist/client/conversation/use-near-bottom-autoscroll.js.map +1 -1
  180. package/dist/client/extensions/AgentNativeExtensionFrame.d.ts.map +1 -1
  181. package/dist/client/extensions/AgentNativeExtensionFrame.js +2 -1
  182. package/dist/client/extensions/AgentNativeExtensionFrame.js.map +1 -1
  183. package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
  184. package/dist/client/extensions/EmbeddedExtension.js +2 -1
  185. package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
  186. package/dist/client/extensions/ExtensionEditor.d.ts.map +1 -1
  187. package/dist/client/extensions/ExtensionEditor.js +5 -2
  188. package/dist/client/extensions/ExtensionEditor.js.map +1 -1
  189. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
  190. package/dist/client/extensions/ExtensionViewer.js +2 -1
  191. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  192. package/dist/client/extensions/InlineExtensionFrame.d.ts.map +1 -1
  193. package/dist/client/extensions/InlineExtensionFrame.js +2 -1
  194. package/dist/client/extensions/InlineExtensionFrame.js.map +1 -1
  195. package/dist/client/extensions/portable-extension.d.ts.map +1 -1
  196. package/dist/client/extensions/portable-extension.js +2 -0
  197. package/dist/client/extensions/portable-extension.js.map +1 -1
  198. package/dist/client/session-replay.d.ts.map +1 -1
  199. package/dist/client/session-replay.js +308 -29
  200. package/dist/client/session-replay.js.map +1 -1
  201. package/dist/client/sse-event-processor.d.ts +5 -0
  202. package/dist/client/sse-event-processor.d.ts.map +1 -1
  203. package/dist/client/sse-event-processor.js +37 -1
  204. package/dist/client/sse-event-processor.js.map +1 -1
  205. package/dist/collab/routes.d.ts +1 -1
  206. package/dist/demo/actions/toggle-demo-mode.js +1 -1
  207. package/dist/demo/actions/toggle-demo-mode.js.map +1 -1
  208. package/dist/demo/config.js +6 -6
  209. package/dist/demo/config.js.map +1 -1
  210. package/dist/demo/fetch-interceptor.d.ts.map +1 -1
  211. package/dist/demo/fetch-interceptor.js +13 -4
  212. package/dist/demo/fetch-interceptor.js.map +1 -1
  213. package/dist/demo/redact.d.ts +7 -7
  214. package/dist/demo/redact.d.ts.map +1 -1
  215. package/dist/demo/redact.js +8 -145
  216. package/dist/demo/redact.js.map +1 -1
  217. package/dist/extensions/html-shell.d.ts.map +1 -1
  218. package/dist/extensions/html-shell.js +2 -0
  219. package/dist/extensions/html-shell.js.map +1 -1
  220. package/dist/extensions/session-replay-iframe.d.ts +10 -0
  221. package/dist/extensions/session-replay-iframe.d.ts.map +1 -0
  222. package/dist/extensions/session-replay-iframe.js +121 -0
  223. package/dist/extensions/session-replay-iframe.js.map +1 -0
  224. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  225. package/dist/integrations/adapters/slack.d.ts.map +1 -1
  226. package/dist/integrations/adapters/slack.js +98 -13
  227. package/dist/integrations/adapters/slack.js.map +1 -1
  228. package/dist/integrations/identity-links-store.d.ts +23 -0
  229. package/dist/integrations/identity-links-store.d.ts.map +1 -0
  230. package/dist/integrations/identity-links-store.js +158 -0
  231. package/dist/integrations/identity-links-store.js.map +1 -0
  232. package/dist/integrations/identity.d.ts +11 -0
  233. package/dist/integrations/identity.d.ts.map +1 -0
  234. package/dist/integrations/identity.js +100 -0
  235. package/dist/integrations/identity.js.map +1 -0
  236. package/dist/integrations/index.d.ts +2 -0
  237. package/dist/integrations/index.d.ts.map +1 -1
  238. package/dist/integrations/index.js +2 -0
  239. package/dist/integrations/index.js.map +1 -1
  240. package/dist/integrations/plugin.d.ts.map +1 -1
  241. package/dist/integrations/plugin.js +43 -1
  242. package/dist/integrations/plugin.js.map +1 -1
  243. package/dist/integrations/types.d.ts +6 -0
  244. package/dist/integrations/types.d.ts.map +1 -1
  245. package/dist/integrations/types.js.map +1 -1
  246. package/dist/mcp/build-server.d.ts +9 -2
  247. package/dist/mcp/build-server.d.ts.map +1 -1
  248. package/dist/mcp/build-server.js +97 -20
  249. package/dist/mcp/build-server.js.map +1 -1
  250. package/dist/mcp/external-agent-policy.d.ts +19 -0
  251. package/dist/mcp/external-agent-policy.d.ts.map +1 -0
  252. package/dist/mcp/external-agent-policy.js +2 -0
  253. package/dist/mcp/external-agent-policy.js.map +1 -0
  254. package/dist/mcp/index.d.ts +1 -0
  255. package/dist/mcp/index.d.ts.map +1 -1
  256. package/dist/mcp/index.js.map +1 -1
  257. package/dist/notifications/routes.d.ts +1 -1
  258. package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
  259. package/dist/scripts/agent-engines/list-agent-engines.js +1 -19
  260. package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
  261. package/dist/server/agent-chat/plugin-options.d.ts +11 -1
  262. package/dist/server/agent-chat/plugin-options.d.ts.map +1 -1
  263. package/dist/server/agent-chat/plugin-options.js.map +1 -1
  264. package/dist/server/agent-chat/script-entries.d.ts.map +1 -1
  265. package/dist/server/agent-chat/script-entries.js +16 -2
  266. package/dist/server/agent-chat/script-entries.js.map +1 -1
  267. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  268. package/dist/server/agent-chat-plugin.js +3 -0
  269. package/dist/server/agent-chat-plugin.js.map +1 -1
  270. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  271. package/dist/server/transcribe-voice.d.ts +1 -1
  272. package/dist/session-replay-iframe-protocol.d.ts +36 -0
  273. package/dist/session-replay-iframe-protocol.d.ts.map +1 -0
  274. package/dist/session-replay-iframe-protocol.js +24 -0
  275. package/dist/session-replay-iframe-protocol.js.map +1 -0
  276. package/dist/shared/reasoning-effort.d.ts +11 -0
  277. package/dist/shared/reasoning-effort.d.ts.map +1 -1
  278. package/dist/shared/reasoning-effort.js +36 -0
  279. package/dist/shared/reasoning-effort.js.map +1 -1
  280. package/dist/styles/agent-conversation.css +26 -0
  281. package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +34 -5
  282. package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +0 -15
  283. package/docs/content/durable-background-runs.mdx +37 -0
  284. package/docs/content/external-agents.mdx +62 -7
  285. package/docs/content/locales/ar-SA/external-agents.mdx +38 -7
  286. package/docs/content/locales/ar-SA/tracking.mdx +2 -0
  287. package/docs/content/locales/de-DE/external-agents.mdx +39 -7
  288. package/docs/content/locales/de-DE/tracking.mdx +2 -0
  289. package/docs/content/locales/es-ES/external-agents.mdx +39 -7
  290. package/docs/content/locales/es-ES/tracking.mdx +2 -0
  291. package/docs/content/locales/fr-FR/external-agents.mdx +39 -7
  292. package/docs/content/locales/fr-FR/tracking.mdx +4 -2
  293. package/docs/content/locales/hi-IN/external-agents.mdx +38 -7
  294. package/docs/content/locales/hi-IN/tracking.mdx +2 -0
  295. package/docs/content/locales/ja-JP/external-agents.mdx +38 -7
  296. package/docs/content/locales/ja-JP/tracking.mdx +2 -0
  297. package/docs/content/locales/ko-KR/external-agents.mdx +38 -7
  298. package/docs/content/locales/ko-KR/tracking.mdx +2 -0
  299. package/docs/content/locales/pt-BR/external-agents.mdx +39 -7
  300. package/docs/content/locales/pt-BR/tracking.mdx +2 -0
  301. package/docs/content/locales/zh-CN/external-agents.mdx +37 -7
  302. package/docs/content/locales/zh-CN/tracking.mdx +2 -0
  303. package/docs/content/locales/zh-TW/durable-background-runs.mdx +14 -0
  304. package/docs/content/locales/zh-TW/external-agents.mdx +37 -7
  305. package/docs/content/locales/zh-TW/tracking.mdx +2 -0
  306. package/docs/content/tracking.mdx +2 -0
  307. package/package.json +2 -2
  308. package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +34 -5
  309. package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +0 -15
  310. package/corpus/core/src/observability/hosted-model-experiment.ts +0 -118
  311. package/dist/observability/hosted-model-experiment.d.ts +0 -39
  312. package/dist/observability/hosted-model-experiment.d.ts.map +0 -1
  313. package/dist/observability/hosted-model-experiment.js +0 -90
  314. package/dist/observability/hosted-model-experiment.js.map +0 -1
@@ -1,3 +1,4 @@
1
+ import { SESSION_REPLAY_IFRAME_ATTRIBUTE, SESSION_REPLAY_IFRAME_PROBE, SESSION_REPLAY_IFRAME_START, SESSION_REPLAY_IFRAME_STOP, } from "../session-replay-iframe-protocol.js";
1
2
  import { getOrCreateAnalyticsAnonymousId, getOrCreateAnalyticsSessionId, } from "./analytics-session.js";
2
3
  import { scrubUrl } from "./url-scrub.js";
3
4
  const DEFAULT_REPLAY_PATH = "/api/analytics/replay";
@@ -16,7 +17,9 @@ const DEFAULT_EVENT_SAMPLING = {
16
17
  };
17
18
  const SESSION_REPLAY_STATE_KEY = Symbol.for("agent-native.client.sessionReplay");
18
19
  const SESSION_REPLAY_ID_STORAGE_KEY = "agent-native.session_replay_id";
20
+ const SESSION_REPLAY_IFRAME_BLOCK_SELECTOR = `iframe[${SESSION_REPLAY_IFRAME_ATTRIBUTE}]`;
19
21
  const DEFAULT_BLOCK_SELECTOR = [
22
+ SESSION_REPLAY_IFRAME_BLOCK_SELECTOR,
20
23
  "[data-sensitive]",
21
24
  "[data-an-block]",
22
25
  "[data-an-private]",
@@ -36,11 +39,28 @@ const DEFAULT_BLOCK_SELECTOR = [
36
39
  const DEFAULT_IGNORE_SELECTOR = ".an-ignore, [data-an-ignore]";
37
40
  const DEFAULT_MASK_TEXT_CLASS = "an-mask";
38
41
  const DEFAULT_MASK_TEXT_SELECTOR = "[data-an-mask]";
42
+ const DEFAULT_MASK_INPUT_OPTIONS = {
43
+ color: true,
44
+ date: true,
45
+ "datetime-local": true,
46
+ email: true,
47
+ month: true,
48
+ number: true,
49
+ password: true,
50
+ range: true,
51
+ search: true,
52
+ tel: true,
53
+ text: true,
54
+ time: true,
55
+ url: true,
56
+ week: true,
57
+ };
39
58
  const DEFAULT_FLUSH_INTERVAL_MS = 5000;
40
59
  const DEFAULT_MAX_DURATION_MS = 30 * 60 * 1000;
41
60
  const DEFAULT_MAX_EVENTS_PER_BATCH = 50;
42
61
  const DEFAULT_MAX_BATCH_BYTES = 256 * 1024;
43
62
  const MAX_KEEPALIVE_REPLAY_UPLOAD_BYTES = 60 * 1024;
63
+ const REPLAY_TEXT_ENCODER = typeof TextEncoder !== "undefined" ? new TextEncoder() : null;
44
64
  const RRWEB_FULL_SNAPSHOT_EVENT_TYPE = 2;
45
65
  /** Cross-tab channel name used by the duplicated-tab claim guard. */
46
66
  const SESSION_REPLAY_BROADCAST_CHANNEL_NAME = "agent-native-session-replay";
@@ -109,9 +129,13 @@ function getState() {
109
129
  flushTimer: null,
110
130
  maxDurationTimer: null,
111
131
  flushing: false,
132
+ pendingFlushReason: null,
133
+ pendingFlushWaiters: [],
134
+ awaitingFullSnapshot: false,
112
135
  stopRecorder: null,
113
136
  restoreUrlMonitor: null,
114
137
  removeLifecycleListeners: null,
138
+ restoreIframeBridge: null,
115
139
  addCustomEvent: null,
116
140
  restoreCaptures: null,
117
141
  options: null,
@@ -124,6 +148,10 @@ function getState() {
124
148
  const state = g[SESSION_REPLAY_STATE_KEY];
125
149
  // Keep Vite HMR safe when an older recorder state survives a module reload.
126
150
  state.resourceNodes ??= new Map();
151
+ state.restoreIframeBridge ??= null;
152
+ state.pendingFlushReason ??= null;
153
+ state.pendingFlushWaiters ??= [];
154
+ state.awaitingFullSnapshot ??= false;
127
155
  return state;
128
156
  }
129
157
  // The replay session record (replayId + sequence counter) lives in
@@ -522,13 +550,17 @@ function normalizeOptions(options) {
522
550
  checkoutEveryNth: options.checkoutEveryNth,
523
551
  checkoutEveryNms: options.checkoutEveryNms,
524
552
  inlineStylesheet: options.inlineStylesheet ?? true,
525
- blockSelector: options.blockSelector || DEFAULT_BLOCK_SELECTOR,
553
+ blockSelector: mergeReplayBlockSelector(options.blockSelector || DEFAULT_BLOCK_SELECTOR),
526
554
  ignoreSelector: options.ignoreSelector || DEFAULT_IGNORE_SELECTOR,
527
555
  maskTextClass: options.maskTextClass || DEFAULT_MASK_TEXT_CLASS,
528
556
  maskTextSelector: options.maskTextSelector || DEFAULT_MASK_TEXT_SELECTOR,
529
557
  maskAllInputs: options.maskAllInputs ?? true,
530
558
  recordCanvas: options.recordCanvas ?? false,
531
- recordCrossOriginIframes: options.recordCrossOriginIframes ?? false,
559
+ // A top-level app can safely aggregate cooperative child recorders. An
560
+ // app embedded by an unrelated cross-origin host must continue emitting
561
+ // and uploading its own events, so it only forwards to a parent when the
562
+ // caller explicitly opts in.
563
+ recordCrossOriginIframes: options.recordCrossOriginIframes ?? window.parent === window,
532
564
  collectFonts: options.collectFonts ?? false,
533
565
  inlineImages: options.inlineImages ?? false,
534
566
  eventSampling: options.eventSampling ?? DEFAULT_EVENT_SAMPLING,
@@ -539,6 +571,11 @@ function normalizeOptions(options) {
539
571
  shouldStart: options.shouldStart,
540
572
  };
541
573
  }
574
+ function mergeReplayBlockSelector(blockSelector) {
575
+ return blockSelector.includes(SESSION_REPLAY_IFRAME_BLOCK_SELECTOR)
576
+ ? blockSelector
577
+ : `${blockSelector}, ${SESSION_REPLAY_IFRAME_BLOCK_SELECTOR}`;
578
+ }
542
579
  /**
543
580
  * Console/network capture default to ON whenever session replay records;
544
581
  * `false` disables a category, an object form overrides its caps. Network
@@ -753,18 +790,25 @@ function replayEventTimestampMs(event) {
753
790
  function enqueueReplayEvent(state, event) {
754
791
  if (!state.options)
755
792
  return;
793
+ const eventType = typeof event.type === "number" ? event.type : null;
794
+ if (state.awaitingFullSnapshot) {
795
+ if (eventType !== RRWEB_FULL_SNAPSHOT_EVENT_TYPE)
796
+ return;
797
+ state.awaitingFullSnapshot = false;
798
+ }
756
799
  const serialized = serializeReplayEvent(event, state.resourceNodes);
757
800
  if (!serialized)
758
801
  return;
759
- const estimatedBytes = serialized.length;
802
+ const estimatedBytes = replaySerializedBytes(serialized);
760
803
  if (state.queue.length > 0 &&
761
804
  state.queuedBytes + estimatedBytes > state.options.maxBatchBytes) {
762
805
  void flushSessionReplay("max-bytes");
763
806
  }
764
807
  state.queue.push({
765
808
  json: serialized,
809
+ byteLength: estimatedBytes,
766
810
  timestampMs: replayEventTimestampMs(event),
767
- type: typeof event.type === "number" ? event.type : null,
811
+ type: eventType,
768
812
  });
769
813
  state.queuedBytes += estimatedBytes;
770
814
  flushQueuedReplayIfNeeded(state);
@@ -989,6 +1033,24 @@ function isFinalFlushReason(reason) {
989
1033
  "max-duration",
990
1034
  ].includes(reason);
991
1035
  }
1036
+ function flushReasonPriority(reason) {
1037
+ // Unload reasons must retain their keepalive sequence reservation even when
1038
+ // another final request (for example, an explicit manual stop) is coalesced.
1039
+ if (reason === "pagehide" || reason === "beforeunload")
1040
+ return 3;
1041
+ if (isFinalFlushReason(reason))
1042
+ return 2;
1043
+ if (reason === "visibility-hidden")
1044
+ return 1;
1045
+ return 0;
1046
+ }
1047
+ function mergePendingFlushReason(current, requested) {
1048
+ if (!current)
1049
+ return requested;
1050
+ return flushReasonPriority(requested) > flushReasonPriority(current)
1051
+ ? requested
1052
+ : current;
1053
+ }
992
1054
  function shouldReserveSequenceBeforeKeepalive(reason) {
993
1055
  return (reason === "pagehide" ||
994
1056
  reason === "beforeunload" ||
@@ -1023,7 +1085,90 @@ function flushQueuedReplayIfNeeded(state) {
1023
1085
  void flushSessionReplay(reason);
1024
1086
  }
1025
1087
  function queuedReplayBytes(events) {
1026
- return events.reduce((total, event) => total + event.json.length, 0);
1088
+ return events.reduce((total, event) => total + queuedReplayEventBytes(event), 0);
1089
+ }
1090
+ function replaySerializedBytes(value) {
1091
+ if (REPLAY_TEXT_ENCODER)
1092
+ return REPLAY_TEXT_ENCODER.encode(value).byteLength;
1093
+ if (typeof Blob !== "undefined")
1094
+ return new Blob([value]).size;
1095
+ return value.length;
1096
+ }
1097
+ function queuedReplayEventBytes(event) {
1098
+ return Number.isFinite(event.byteLength)
1099
+ ? event.byteLength
1100
+ : replaySerializedBytes(event.json);
1101
+ }
1102
+ /**
1103
+ * Remove one bounded FIFO prefix from the live queue.
1104
+ *
1105
+ * Threshold-triggered flushes may arrive while another upload is active. The
1106
+ * old `queue.splice(0)` drained that entire accumulated backlog on the next
1107
+ * flush, bypassing both byte and event caps. Keep FullSnapshots isolated and
1108
+ * always take at least one event so an individually large snapshot can still
1109
+ * make progress.
1110
+ */
1111
+ function takeQueuedReplayBatch(state) {
1112
+ const options = state.options;
1113
+ if (!options || state.queue.length === 0)
1114
+ return [];
1115
+ let count = 0;
1116
+ let bytes = 0;
1117
+ for (const event of state.queue) {
1118
+ if (count > 0 && event.type === RRWEB_FULL_SNAPSHOT_EVENT_TYPE)
1119
+ break;
1120
+ if (count > 0 &&
1121
+ (count >= options.maxEventsPerBatch ||
1122
+ bytes + queuedReplayEventBytes(event) > options.maxBatchBytes)) {
1123
+ break;
1124
+ }
1125
+ count += 1;
1126
+ bytes += queuedReplayEventBytes(event);
1127
+ if (event.type === RRWEB_FULL_SNAPSHOT_EVENT_TYPE)
1128
+ break;
1129
+ }
1130
+ const events = state.queue.splice(0, Math.max(1, count));
1131
+ state.queuedBytes = queuedReplayBytes(state.queue);
1132
+ return events;
1133
+ }
1134
+ function splitReplayBatch(events) {
1135
+ if (events.length < 2)
1136
+ return null;
1137
+ const targetBytes = queuedReplayBytes(events) / 2;
1138
+ let splitAt = 1;
1139
+ let bytes = events[0] ? queuedReplayEventBytes(events[0]) : 0;
1140
+ while (splitAt < events.length - 1 && bytes < targetBytes) {
1141
+ const event = events[splitAt];
1142
+ if (event)
1143
+ bytes += queuedReplayEventBytes(event);
1144
+ splitAt += 1;
1145
+ }
1146
+ return [events.slice(0, splitAt), events.slice(splitAt)];
1147
+ }
1148
+ function replayBatchNeedsDomReset(events) {
1149
+ return events.some((event) => {
1150
+ if (event.type === RRWEB_FULL_SNAPSHOT_EVENT_TYPE)
1151
+ return true;
1152
+ if (event.type !== 3)
1153
+ return false;
1154
+ try {
1155
+ const parsed = JSON.parse(event.json);
1156
+ // rrweb IncrementalSource.Mutation is zero. Dropping one may leave later
1157
+ // node references dangling until another FullSnapshot resets the mirror.
1158
+ return parsed.data?.source === 0;
1159
+ }
1160
+ catch {
1161
+ return true;
1162
+ }
1163
+ });
1164
+ }
1165
+ function quarantinePendingReplayUntilFullSnapshot(state) {
1166
+ const pending = [...state.retryBatches.flat(), ...state.queue];
1167
+ const resetAt = pending.findIndex((event) => event.type === RRWEB_FULL_SNAPSHOT_EVENT_TYPE);
1168
+ state.retryBatches = [];
1169
+ state.queue = resetAt >= 0 ? pending.slice(resetAt) : [];
1170
+ state.queuedBytes = queuedReplayBytes(state.queue);
1171
+ state.awaitingFullSnapshot = resetAt < 0;
1027
1172
  }
1028
1173
  function restoreReplayEvents(state, events) {
1029
1174
  state.retryBatches.unshift(events);
@@ -1044,10 +1189,17 @@ function rollbackReplaySequenceReservation(state, payload) {
1044
1189
  }
1045
1190
  export async function flushSessionReplay(reason = "manual") {
1046
1191
  const state = getState();
1047
- if (!state.options || !hasPendingReplayBatch(state) || state.flushing)
1192
+ if (!state.options)
1048
1193
  return;
1049
- const events = state.retryBatches.shift() ?? state.queue.splice(0);
1050
- state.queuedBytes = queuedReplayBytes(state.queue);
1194
+ if (state.flushing) {
1195
+ state.pendingFlushReason = mergePendingFlushReason(state.pendingFlushReason, reason);
1196
+ return new Promise((resolve) => {
1197
+ state.pendingFlushWaiters.push(resolve);
1198
+ });
1199
+ }
1200
+ if (!hasPendingReplayBatch(state))
1201
+ return;
1202
+ const events = state.retryBatches.shift() ?? takeQueuedReplayBatch(state);
1051
1203
  const payload = buildReplayBody(state, reason, events);
1052
1204
  if (!payload || !state.options) {
1053
1205
  restoreReplayEvents(state, events);
@@ -1056,6 +1208,8 @@ export async function flushSessionReplay(reason = "manual") {
1056
1208
  state.flushing = true;
1057
1209
  let uploaded = false;
1058
1210
  let reservedSequence = false;
1211
+ let splitRejectedBatch = false;
1212
+ let droppedOversizedBatch = false;
1059
1213
  let definitiveClientErrorStatus = null;
1060
1214
  try {
1061
1215
  await sendReplayUpload(state.options, payload.body, {
@@ -1078,9 +1232,32 @@ export async function flushSessionReplay(reason = "manual") {
1078
1232
  // never succeed by retrying the exact same batch -- requeuing it would
1079
1233
  // just spin forever, blocking every later batch behind it (flushes are
1080
1234
  // FIFO via `retryBatches`). Drop it and move on instead.
1235
+ const rejectedStatus = error instanceof ReplayUploadHttpError ? error.status : null;
1236
+ const splitBatch = rejectedStatus === 413 ? splitReplayBatch(events) : null;
1237
+ const isUnsplittableOversizedBatch = rejectedStatus === 413 && splitBatch === null;
1081
1238
  const isDefinitiveClientError = error instanceof ReplayUploadHttpError &&
1082
- isDefinitiveReplayUploadClientError(error.status);
1083
- if (isDefinitiveClientError) {
1239
+ isDefinitiveReplayUploadClientError(error.status) &&
1240
+ !splitBatch &&
1241
+ !isUnsplittableOversizedBatch;
1242
+ if (splitBatch) {
1243
+ // A server or platform can enforce a stricter decompressed-body limit
1244
+ // than the recorder's configured queue cap. Bisect in FIFO order and
1245
+ // retry both halves at the same sequence; only successful halves advance
1246
+ // it, so no event is duplicated or skipped.
1247
+ state.retryBatches.unshift(...splitBatch);
1248
+ splitRejectedBatch = true;
1249
+ }
1250
+ else if (isUnsplittableOversizedBatch) {
1251
+ // This one event cannot be made any smaller. Drop only the rejected
1252
+ // singleton and keep later retry halves/live batches in FIFO order. If
1253
+ // it carried DOM structure, quarantine dependent mutations until a new
1254
+ // FullSnapshot can safely re-anchor rrweb's node mirror.
1255
+ droppedOversizedBatch = true;
1256
+ if (replayBatchNeedsDomReset(events)) {
1257
+ quarantinePendingReplayUntilFullSnapshot(state);
1258
+ }
1259
+ }
1260
+ else if (isDefinitiveClientError) {
1084
1261
  // Continuing after a checksum/sequence conflict would reuse the same
1085
1262
  // rejected sequence forever. More importantly, advancing past it would
1086
1263
  // append mutations to a replay whose DOM stream may belong to another
@@ -1100,7 +1277,13 @@ export async function flushSessionReplay(reason = "manual") {
1100
1277
  const previousInternal = replayCaptureInternal;
1101
1278
  replayCaptureInternal = true;
1102
1279
  try {
1103
- if (isDefinitiveClientError) {
1280
+ if (splitRejectedBatch) {
1281
+ console.warn("[session-replay] splitting oversized upload (HTTP 413)", error);
1282
+ }
1283
+ else if (droppedOversizedBatch) {
1284
+ console.warn("[session-replay] dropping oversized replay event (HTTP 413)", error);
1285
+ }
1286
+ else if (isDefinitiveClientError) {
1104
1287
  console.warn(`[session-replay] dropping upload (HTTP ${error.status})`, error);
1105
1288
  }
1106
1289
  else {
@@ -1114,8 +1297,36 @@ export async function flushSessionReplay(reason = "manual") {
1114
1297
  finally {
1115
1298
  state.flushing = false;
1116
1299
  }
1117
- if (uploaded && hasPendingReplayBatch(state)) {
1118
- flushQueuedReplayIfNeeded(state);
1300
+ const coalescedReason = state.pendingFlushReason;
1301
+ const coalescedWaiters = coalescedReason
1302
+ ? state.pendingFlushWaiters.splice(0)
1303
+ : [];
1304
+ if (coalescedReason)
1305
+ state.pendingFlushReason = null;
1306
+ if (coalescedReason) {
1307
+ // A stop/unload request that arrived during this upload owns the tail.
1308
+ // Its higher-priority reason must replace threshold/internal reasons so a
1309
+ // small final batch is not stranded or mislabeled as active.
1310
+ await flushSessionReplay(coalescedReason);
1311
+ }
1312
+ else if (splitRejectedBatch || droppedOversizedBatch) {
1313
+ // Preserve final-status and unload semantics through every half. In
1314
+ // particular, pagehide/beforeunload retries must still reserve their
1315
+ // sequence before a keepalive fetch, and completed flushes must not be
1316
+ // rewritten to an internal recovery reason/status.
1317
+ await flushSessionReplay(reason);
1318
+ }
1319
+ else if (uploaded && hasPendingReplayBatch(state)) {
1320
+ const mustContinue = state.retryBatches.length > 0 ||
1321
+ isFinalFlushReason(reason) ||
1322
+ shouldFlushQueuedReplay(state);
1323
+ if (mustContinue) {
1324
+ if (isFinalFlushReason(reason)) {
1325
+ await flushSessionReplay(reason);
1326
+ }
1327
+ else
1328
+ void flushSessionReplay(reason);
1329
+ }
1119
1330
  }
1120
1331
  if (definitiveClientErrorStatus !== null &&
1121
1332
  state.replayId === payload.replayId) {
@@ -1155,6 +1366,8 @@ export async function flushSessionReplay(reason = "manual") {
1155
1366
  // best-effort telemetry must never interfere with recording recovery
1156
1367
  }
1157
1368
  }
1369
+ for (const resolve of coalescedWaiters)
1370
+ resolve();
1158
1371
  }
1159
1372
  /**
1160
1373
  * Restart a recorder whose replay identity was rejected without routing the
@@ -1239,6 +1452,80 @@ function installLifecycleListeners(state) {
1239
1452
  state.removeLifecycleListeners = null;
1240
1453
  };
1241
1454
  }
1455
+ function markedSessionReplayIframes() {
1456
+ if (typeof document.querySelectorAll !== "function")
1457
+ return [];
1458
+ return Array.from(document.querySelectorAll(`iframe[${SESSION_REPLAY_IFRAME_ATTRIBUTE}]`));
1459
+ }
1460
+ function markedSessionReplayIframeForSource(source) {
1461
+ if (!source)
1462
+ return null;
1463
+ return (markedSessionReplayIframes().find((iframe) => iframe.contentWindow === source) ?? null);
1464
+ }
1465
+ function sessionReplayIframePrivacyOptions(options) {
1466
+ return {
1467
+ blockSelector: options.blockSelector,
1468
+ ignoreSelector: options.ignoreSelector,
1469
+ maskTextClass: options.maskTextClass,
1470
+ maskTextSelector: options.maskTextSelector,
1471
+ maskAllInputs: options.maskAllInputs,
1472
+ maskInputOptions: DEFAULT_MASK_INPUT_OPTIONS,
1473
+ recordCanvas: options.recordCanvas,
1474
+ collectFonts: options.collectFonts,
1475
+ inlineImages: options.inlineImages,
1476
+ sampling: options.eventSampling,
1477
+ };
1478
+ }
1479
+ function postSessionReplayIframeMessage(iframe, message) {
1480
+ try {
1481
+ iframe.contentWindow?.postMessage(message, "*");
1482
+ }
1483
+ catch {
1484
+ // The frame may have navigated or detached between discovery and send.
1485
+ }
1486
+ }
1487
+ /**
1488
+ * Cooperative opaque/cross-origin iframe recording.
1489
+ *
1490
+ * rrweb cannot inspect these documents from the host. Framework-owned child
1491
+ * frames carry a marker and inject a tiny recorder that probes its direct
1492
+ * parent. Only an active host recorder responds, and only when the probe's
1493
+ * source is the contentWindow of a currently marked direct iframe.
1494
+ */
1495
+ function installSessionReplayIframeBridge(state, options) {
1496
+ if (!options.recordCrossOriginIframes || state.restoreIframeBridge)
1497
+ return;
1498
+ const startMessage = {
1499
+ type: SESSION_REPLAY_IFRAME_START,
1500
+ options: sessionReplayIframePrivacyOptions(options),
1501
+ };
1502
+ const stopMessage = {
1503
+ type: SESSION_REPLAY_IFRAME_STOP,
1504
+ };
1505
+ const sendStart = (iframe) => postSessionReplayIframeMessage(iframe, startMessage);
1506
+ const onMessage = (event) => {
1507
+ if (!state.active)
1508
+ return;
1509
+ if (!event.data ||
1510
+ typeof event.data !== "object" ||
1511
+ event.data.type !== SESSION_REPLAY_IFRAME_PROBE) {
1512
+ return;
1513
+ }
1514
+ const iframe = markedSessionReplayIframeForSource(event.source);
1515
+ if (iframe)
1516
+ sendStart(iframe);
1517
+ };
1518
+ window.addEventListener("message", onMessage);
1519
+ for (const iframe of markedSessionReplayIframes())
1520
+ sendStart(iframe);
1521
+ state.restoreIframeBridge = () => {
1522
+ window.removeEventListener("message", onMessage);
1523
+ for (const iframe of markedSessionReplayIframes()) {
1524
+ postSessionReplayIframeMessage(iframe, stopMessage);
1525
+ }
1526
+ state.restoreIframeBridge = null;
1527
+ };
1528
+ }
1242
1529
  function truncateCaptureText(value, maxLength) {
1243
1530
  return value.length > maxLength ? value.slice(0, maxLength) : value;
1244
1531
  }
@@ -1952,6 +2239,10 @@ async function startSessionReplayRecorder(state, normalized, sessionId, sampled,
1952
2239
  state.queue = [];
1953
2240
  state.queuedBytes = 0;
1954
2241
  state.retryBatches = [];
2242
+ state.pendingFlushReason = null;
2243
+ for (const resolve of state.pendingFlushWaiters.splice(0))
2244
+ resolve();
2245
+ state.awaitingFullSnapshot = false;
1955
2246
  state.resourceNodes.clear();
1956
2247
  state.stopRecorder = null;
1957
2248
  state.broadcastChannel = replayChannel;
@@ -1975,22 +2266,7 @@ async function startSessionReplayRecorder(state, normalized, sessionId, sampled,
1975
2266
  recordCrossOriginIframes: normalized.recordCrossOriginIframes,
1976
2267
  collectFonts: normalized.collectFonts,
1977
2268
  inlineImages: normalized.inlineImages,
1978
- maskInputOptions: {
1979
- color: true,
1980
- date: true,
1981
- "datetime-local": true,
1982
- email: true,
1983
- month: true,
1984
- number: true,
1985
- password: true,
1986
- range: true,
1987
- search: true,
1988
- tel: true,
1989
- text: true,
1990
- time: true,
1991
- url: true,
1992
- week: true,
1993
- },
2269
+ maskInputOptions: DEFAULT_MASK_INPUT_OPTIONS,
1994
2270
  });
1995
2271
  if (typeof stopRecorder !== "function") {
1996
2272
  state.active = false;
@@ -2012,6 +2288,7 @@ async function startSessionReplayRecorder(state, normalized, sessionId, sampled,
2012
2288
  state.maxDurationTimer = window.setTimeout(() => stopSessionReplay("max-duration"), normalized.maxDurationMs);
2013
2289
  installUrlMonitor(state);
2014
2290
  installLifecycleListeners(state);
2291
+ installSessionReplayIframeBridge(state, normalized);
2015
2292
  state.addCustomEvent =
2016
2293
  typeof rrweb.record.addCustomEvent === "function"
2017
2294
  ? rrweb.record.addCustomEvent
@@ -2032,6 +2309,7 @@ async function startSessionReplayRecorder(state, normalized, sessionId, sampled,
2032
2309
  // best-effort interceptor teardown
2033
2310
  }
2034
2311
  state.restoreCaptures = null;
2312
+ state.restoreIframeBridge?.();
2035
2313
  state.addCustomEvent = null;
2036
2314
  state.active = false;
2037
2315
  state.options = null;
@@ -2062,6 +2340,7 @@ export async function stopSessionReplay(reason = "manual") {
2062
2340
  // best-effort interceptor teardown
2063
2341
  }
2064
2342
  state.restoreCaptures = null;
2343
+ state.restoreIframeBridge?.();
2065
2344
  state.active = false;
2066
2345
  state.addCustomEvent = null;
2067
2346
  try {