@agent-native/core 0.91.2 → 0.92.1

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 (538) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +31 -0
  3. package/corpus/core/docs/content/faq.mdx +17 -0
  4. package/corpus/core/docs/content/notifications.mdx +12 -6
  5. package/corpus/core/package.json +1 -1
  6. package/corpus/core/src/agent/production-agent.ts +140 -46
  7. package/corpus/core/src/agent/tool-search.ts +71 -4
  8. package/corpus/core/src/application-state/store.ts +12 -1
  9. package/corpus/core/src/cli/index.ts +20 -0
  10. package/corpus/core/src/cli/upgrade.ts +798 -0
  11. package/corpus/core/src/client/AssistantChat.tsx +28 -15
  12. package/corpus/core/src/client/HighlightedCodeBlock.tsx +20 -3
  13. package/corpus/core/src/client/PoweredByBadge.tsx +1 -8
  14. package/corpus/core/src/client/agent-chat-adapter.ts +68 -16
  15. package/corpus/core/src/client/chat/message-components.tsx +85 -8
  16. package/corpus/core/src/client/chat/tool-call-display.tsx +355 -144
  17. package/corpus/core/src/client/chat/widgets/DataTableWidget.tsx +52 -1
  18. package/corpus/core/src/client/code-agent-chat-adapter.ts +2 -9
  19. package/corpus/core/src/client/db-admin/TableEditor.tsx +49 -0
  20. package/corpus/core/src/client/db-admin/export-utils.ts +13 -4
  21. package/corpus/core/src/client/db-admin/useAgentSync.ts +72 -0
  22. package/corpus/core/src/client/error-capture.ts +69 -7
  23. package/corpus/core/src/client/extensions/EmbeddedExtension.tsx +5 -1
  24. package/corpus/core/src/client/extensions/ExtensionViewer.tsx +53 -8
  25. package/corpus/core/src/client/extensions/InlineExtensionFrame.tsx +5 -1
  26. package/corpus/core/src/client/extensions/portable-extension.ts +1 -0
  27. package/corpus/core/src/client/org/OrgSwitcher.tsx +12 -9
  28. package/corpus/core/src/client/org/TeamPage.tsx +77 -71
  29. package/corpus/core/src/client/session-replay.ts +3 -97
  30. package/corpus/core/src/client/settings/SettingsPanel.tsx +738 -441
  31. package/corpus/core/src/client/settings/SettingsSection.tsx +161 -17
  32. package/corpus/core/src/client/settings/SettingsTabsPage.tsx +25 -9
  33. package/corpus/core/src/client/sse-event-processor.ts +29 -2
  34. package/corpus/core/src/db-admin/agent-tools.ts +8 -2
  35. package/corpus/core/src/db-admin/operations.ts +116 -4
  36. package/corpus/core/src/db-admin/routes.ts +1 -0
  37. package/corpus/core/src/db-admin/types.ts +4 -0
  38. package/corpus/core/src/extensions/actions.ts +113 -5
  39. package/corpus/core/src/extensions/html-shell.ts +5 -4
  40. package/corpus/core/src/extensions/routes.ts +10 -0
  41. package/corpus/core/src/navigation/index.ts +1 -1
  42. package/corpus/core/src/notifications/channels.ts +88 -25
  43. package/corpus/core/src/notifications/registry.ts +17 -3
  44. package/corpus/core/src/notifications/types.ts +4 -1
  45. package/corpus/core/src/resources/handlers.ts +10 -8
  46. package/corpus/core/src/server/agent-chat-plugin.ts +7 -3
  47. package/corpus/core/src/server/poll.ts +293 -8
  48. package/corpus/core/src/server/request-context.ts +7 -0
  49. package/corpus/core/src/styles/agent-conversation.css +1 -1
  50. package/corpus/core/src/styles/agent-native.css +27 -0
  51. package/corpus/core/src/templates/default/.agents/skills/actions/SKILL.md +5 -0
  52. package/corpus/core/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
  53. package/corpus/core/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
  54. package/corpus/core/src/templates/default/.agents/skills/security/SKILL.md +7 -0
  55. package/corpus/core/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +20 -2
  56. package/corpus/core/src/templates/default/.agents/skills/storing-data/SKILL.md +5 -1
  57. package/corpus/core/src/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  58. package/corpus/core/src/templates/default/AGENTS.md +14 -5
  59. package/corpus/core/src/templates/default/package.json +2 -1
  60. package/corpus/core/src/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  61. package/corpus/core/src/templates/headless/AGENTS.md +13 -3
  62. package/corpus/core/src/templates/headless/package.json +1 -0
  63. package/corpus/core/src/templates/workspace-core/.agents/skills/actions/SKILL.md +5 -0
  64. package/corpus/core/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
  65. package/corpus/core/src/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +4 -0
  66. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -0
  67. package/corpus/core/src/templates/workspace-core/.agents/skills/performance/SKILL.md +4 -0
  68. package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
  69. package/corpus/core/src/templates/workspace-core/.agents/skills/security/SKILL.md +7 -0
  70. package/corpus/core/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +20 -2
  71. package/corpus/core/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +5 -1
  72. package/corpus/core/src/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  73. package/corpus/core/src/templates/workspace-core/AGENTS.md +7 -1
  74. package/corpus/core/src/templates/workspace-root/AGENTS.md +17 -5
  75. package/corpus/core/src/templates/workspace-root/package.json +1 -0
  76. package/corpus/templates/analytics/.agents/skills/actions/SKILL.md +5 -0
  77. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +10 -0
  78. package/corpus/templates/analytics/.agents/skills/real-time-sync/SKILL.md +1 -1
  79. package/corpus/templates/analytics/.agents/skills/security/SKILL.md +7 -0
  80. package/corpus/templates/analytics/.agents/skills/self-modifying-code/SKILL.md +20 -2
  81. package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +5 -6
  82. package/corpus/templates/analytics/.agents/skills/storing-data/SKILL.md +5 -1
  83. package/corpus/templates/analytics/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  84. package/corpus/templates/analytics/AGENTS.md +39 -18
  85. package/corpus/templates/analytics/actions/capture-test-error.ts +4 -0
  86. package/corpus/templates/analytics/actions/get-analytics-alert-rule-defaults.ts +23 -0
  87. package/corpus/templates/analytics/actions/get-error-issue.ts +1 -1
  88. package/corpus/templates/analytics/actions/list-analysis-revisions.ts +40 -0
  89. package/corpus/templates/analytics/actions/list-dashboard-revisions.ts +40 -0
  90. package/corpus/templates/analytics/actions/list-dashboard-usage-stats.ts +299 -0
  91. package/corpus/templates/analytics/actions/navigate.ts +4 -2
  92. package/corpus/templates/analytics/actions/restore-analysis-revision.ts +43 -0
  93. package/corpus/templates/analytics/actions/restore-dashboard-revision.ts +68 -0
  94. package/corpus/templates/analytics/actions/save-analytics-alert-rule.ts +14 -0
  95. package/corpus/templates/analytics/actions/save-monitor.ts +15 -1
  96. package/corpus/templates/analytics/actions/view-screen.ts +24 -0
  97. package/corpus/templates/analytics/app/components/analysis/AnalysisHistoryPanel.tsx +181 -0
  98. package/corpus/templates/analytics/app/components/dashboard/DashboardHistoryPanel.tsx +184 -0
  99. package/corpus/templates/analytics/app/components/dashboard/DataTable.tsx +41 -6
  100. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +122 -11
  101. package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +22 -16
  102. package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -1
  103. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +27 -21
  104. package/corpus/templates/analytics/app/hooks/use-analysis-revisions.ts +43 -0
  105. package/corpus/templates/analytics/app/hooks/use-dashboard-chat-context.ts +110 -0
  106. package/corpus/templates/analytics/app/hooks/use-dashboard-revisions.ts +43 -0
  107. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +8 -3
  108. package/corpus/templates/analytics/app/i18n/zh-TW.ts +64 -2
  109. package/corpus/templates/analytics/app/i18n-data.ts +783 -3
  110. package/corpus/templates/analytics/app/pages/Agents.tsx +359 -19
  111. package/corpus/templates/analytics/app/pages/Settings.tsx +3 -2
  112. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +34 -1
  113. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +28 -0
  114. package/corpus/templates/analytics/app/pages/analyses/AnalysisDetail.tsx +18 -1
  115. package/corpus/templates/analytics/app/pages/monitoring/ErrorsPanel.tsx +7 -10
  116. package/corpus/templates/analytics/app/pages/monitoring/MonitoringPage.tsx +8 -2
  117. package/corpus/templates/analytics/app/pages/monitoring/errors/IssueDetail.tsx +479 -23
  118. package/corpus/templates/analytics/app/pages/monitoring/errors/IssueList.tsx +0 -9
  119. package/corpus/templates/analytics/app/pages/monitoring/errors/i18n.ts +11 -0
  120. package/corpus/templates/analytics/app/pages/monitoring/errors/types.ts +9 -1
  121. package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorFormPage.tsx +157 -35
  122. package/corpus/templates/analytics/app/pages/monitoring/uptime/i18n.ts +17 -2
  123. package/corpus/templates/analytics/app/pages/monitoring/uptime/types.ts +4 -0
  124. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +80 -220
  125. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +9 -99
  126. package/corpus/templates/analytics/app/pages/settings/AlertRulesSettingsCard.tsx +262 -104
  127. package/corpus/templates/analytics/app/routes/team.tsx +1 -1
  128. package/corpus/templates/analytics/changelog/2026-07-08-admins-can-audit-dashboard-usage-ownership-and-cleanup-signa.md +6 -0
  129. package/corpus/templates/analytics/changelog/2026-07-08-agent-monitoring-stays-available-to-non-admins.md +6 -0
  130. package/corpus/templates/analytics/changelog/2026-07-08-alert-rules-are-easier-to-scan-expand-and-edit-from-settings.md +6 -0
  131. package/corpus/templates/analytics/changelog/2026-07-08-analytics-alert-forms-remember-last-email-recipients.md +6 -0
  132. package/corpus/templates/analytics/changelog/2026-07-08-analytics-alert-rules-can-now-use-per-rule-slack-and-webhook.md +6 -0
  133. package/corpus/templates/analytics/changelog/2026-07-08-dashboard-history-and-chat-context.md +5 -0
  134. package/corpus/templates/analytics/changelog/2026-07-08-dashboard-tables-keep-their-size-while-loading.md +6 -0
  135. package/corpus/templates/analytics/changelog/2026-07-08-dashboard-usage-now-counts-explorer-dashboard-traffic.md +6 -0
  136. package/corpus/templates/analytics/changelog/2026-07-08-demo-mode-session-emails-are-filtered-and-anonymized.md +6 -0
  137. package/corpus/templates/analytics/changelog/2026-07-08-error-issue-detail-adds-stack-traces-and-frequency-bars.md +6 -0
  138. package/corpus/templates/analytics/changelog/2026-07-08-error-issue-detail-now-shows-the-latest-occurrence-message-a.md +6 -0
  139. package/corpus/templates/analytics/changelog/2026-07-08-monitoring-errors-only-show-test-action-when-empty.md +6 -0
  140. package/corpus/templates/analytics/changelog/2026-07-08-monitoring-uptime-and-errors-tabs-now-clearly-show-which-view-is-active.md +6 -0
  141. package/corpus/templates/analytics/changelog/2026-07-08-production-session-replay-now-requires-private-blob-storage-.md +6 -0
  142. package/corpus/templates/analytics/changelog/2026-07-08-session-replay-uses-stock-rrweb-sizing-again-so-recorded.md +6 -0
  143. package/corpus/templates/analytics/changelog/2026-07-08-shared-extension-links-now-show-a-clear-message-when-you-do-.md +6 -0
  144. package/corpus/templates/analytics/changelog/2026-07-08-sidebar-dashboard-menus-now-open-above-the-dashboard-canvas.md +6 -0
  145. package/corpus/templates/analytics/changelog/2026-07-08-team-settings-show-access-controls-next-to-member-lists.md +6 -0
  146. package/corpus/templates/analytics/changelog/2026-07-08-uptime-alerting-clarifies-in-app-inbox-vs-email-and-lets-you-paste-slack-or-webhook-urls-per-monitor.md +6 -0
  147. package/corpus/templates/analytics/changelog/2026-07-08-uptime-monitors-now-use-a-10-second-request-timeout-by-defau.md +6 -0
  148. package/corpus/templates/analytics/docs/uptime-monitoring.md +13 -11
  149. package/corpus/templates/analytics/server/db/schema-monitoring.ts +5 -1
  150. package/corpus/templates/analytics/server/db/schema.ts +56 -0
  151. package/corpus/templates/analytics/server/lib/analytics-alerts.ts +92 -0
  152. package/corpus/templates/analytics/server/lib/dashboards-store.ts +334 -5
  153. package/corpus/templates/analytics/server/lib/error-capture.ts +231 -36
  154. package/corpus/templates/analytics/server/lib/session-replay.ts +114 -8
  155. package/corpus/templates/analytics/server/lib/uptime-monitors.ts +65 -16
  156. package/corpus/templates/analytics/server/plugins/db.ts +122 -2
  157. package/corpus/templates/analytics/server/routes/api/dashboard-agent-context.json.get.ts +1 -0
  158. package/corpus/templates/assets/.agents/skills/actions/SKILL.md +5 -0
  159. package/corpus/templates/assets/.agents/skills/real-time-sync/SKILL.md +1 -1
  160. package/corpus/templates/assets/.agents/skills/security/SKILL.md +7 -0
  161. package/corpus/templates/assets/.agents/skills/self-modifying-code/SKILL.md +20 -2
  162. package/corpus/templates/assets/.agents/skills/storing-data/SKILL.md +5 -1
  163. package/corpus/templates/assets/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  164. package/corpus/templates/assets/AGENTS.md +4 -0
  165. package/corpus/templates/assets/app/routes/settings.tsx +1 -1
  166. package/corpus/templates/assets/app/routes/team.tsx +1 -1
  167. package/corpus/templates/brain/.agents/skills/actions/SKILL.md +5 -0
  168. package/corpus/templates/brain/.agents/skills/adding-a-feature/SKILL.md +5 -0
  169. package/corpus/templates/brain/.agents/skills/real-time-sync/SKILL.md +1 -1
  170. package/corpus/templates/brain/.agents/skills/security/SKILL.md +7 -0
  171. package/corpus/templates/brain/.agents/skills/self-modifying-code/SKILL.md +20 -2
  172. package/corpus/templates/brain/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  173. package/corpus/templates/brain/AGENTS.md +4 -0
  174. package/corpus/templates/brain/app/routes/team.tsx +1 -1
  175. package/corpus/templates/calendar/.agents/skills/actions/SKILL.md +5 -0
  176. package/corpus/templates/calendar/.agents/skills/real-time-sync/SKILL.md +1 -1
  177. package/corpus/templates/calendar/.agents/skills/security/SKILL.md +7 -0
  178. package/corpus/templates/calendar/.agents/skills/self-modifying-code/SKILL.md +20 -2
  179. package/corpus/templates/calendar/.agents/skills/storing-data/SKILL.md +5 -1
  180. package/corpus/templates/calendar/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  181. package/corpus/templates/calendar/AGENTS.md +4 -0
  182. package/corpus/templates/calendar/app/components/calendar/DayView.tsx +11 -2
  183. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +21 -8
  184. package/corpus/templates/calendar/app/components/calendar/MonthView.tsx +7 -1
  185. package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +11 -2
  186. package/corpus/templates/calendar/app/lib/popover-click-guard.ts +48 -4
  187. package/corpus/templates/calendar/app/pages/Settings.tsx +1 -1
  188. package/corpus/templates/calendar/app/routes/_app.team.tsx +1 -1
  189. package/corpus/templates/calendar/changelog/2026-07-08-clicking-empty-calendar-space-closes-an-open-event-popover-b.md +6 -0
  190. package/corpus/templates/chat/.agents/skills/actions/SKILL.md +5 -0
  191. package/corpus/templates/chat/.agents/skills/adding-a-feature/SKILL.md +5 -0
  192. package/corpus/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
  193. package/corpus/templates/chat/.agents/skills/security/SKILL.md +7 -0
  194. package/corpus/templates/chat/.agents/skills/self-modifying-code/SKILL.md +20 -2
  195. package/corpus/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  196. package/corpus/templates/chat/AGENTS.md +4 -0
  197. package/corpus/templates/chat/app/hooks/use-navigation-state.ts +1 -1
  198. package/corpus/templates/chat/app/routes/settings.tsx +2 -2
  199. package/corpus/templates/chat/app/routes/team.tsx +1 -1
  200. package/corpus/templates/clips/.agents/skills/actions/SKILL.md +5 -0
  201. package/corpus/templates/clips/.agents/skills/security/SKILL.md +7 -0
  202. package/corpus/templates/clips/.agents/skills/self-modifying-code/SKILL.md +20 -2
  203. package/corpus/templates/clips/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  204. package/corpus/templates/clips/AGENTS.md +4 -0
  205. package/corpus/templates/clips/actions/finalize-recording.ts +9 -3
  206. package/corpus/templates/clips/actions/set-thumbnail.ts +11 -2
  207. package/corpus/templates/clips/app/components/meetings/canvas-editor.tsx +1 -7
  208. package/corpus/templates/clips/app/components/player/player-controls.tsx +21 -13
  209. package/corpus/templates/clips/app/components/player/video-player.tsx +30 -75
  210. package/corpus/templates/clips/app/i18n/ar-SA.ts +6 -5
  211. package/corpus/templates/clips/app/i18n/de-DE.ts +6 -6
  212. package/corpus/templates/clips/app/i18n/en-US.ts +6 -5
  213. package/corpus/templates/clips/app/i18n/es-ES.ts +6 -5
  214. package/corpus/templates/clips/app/i18n/fr-FR.ts +6 -6
  215. package/corpus/templates/clips/app/i18n/hi-IN.ts +6 -5
  216. package/corpus/templates/clips/app/i18n/ja-JP.ts +6 -5
  217. package/corpus/templates/clips/app/i18n/ko-KR.ts +6 -5
  218. package/corpus/templates/clips/app/i18n/pt-BR.ts +6 -5
  219. package/corpus/templates/clips/app/i18n/zh-CN.ts +6 -5
  220. package/corpus/templates/clips/app/i18n/zh-TW.ts +6 -5
  221. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +51 -118
  222. package/corpus/templates/clips/changelog/2026-07-08-desktop-meeting-notes-stay-active-from-tray-and-shortcut-controls.md +6 -0
  223. package/corpus/templates/clips/changelog/2026-07-08-desktop-meeting-popovers-can-start-notes-and-join-the-meetin.md +6 -0
  224. package/corpus/templates/clips/changelog/2026-07-08-hosted-clip-uploads-now-clear-failed-buffered-chunks.md +6 -0
  225. package/corpus/templates/clips/changelog/2026-07-08-hosted-recording-uploads-now-avoid-sql-chunk-storage.md +6 -0
  226. package/corpus/templates/clips/changelog/2026-07-08-meeting-notes-keep-their-recording-state-when-the-desktop.md +6 -0
  227. package/corpus/templates/clips/changelog/2026-07-08-meeting-recaps-now-keep-summaries-action-items-and-transcrip.md +6 -0
  228. package/corpus/templates/clips/changelog/2026-07-08-meeting-reminder-dropdowns-now-expand-fully-instead-of-being.md +6 -0
  229. package/corpus/templates/clips/changelog/2026-07-08-video-playback-controls-now-match-loom-style-5-second-skips-.md +6 -0
  230. package/corpus/templates/clips/desktop/src/app.tsx +123 -3
  231. package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +15 -1
  232. package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +23 -0
  233. package/corpus/templates/clips/desktop/src/styles.css +23 -1
  234. package/corpus/templates/clips/desktop/src-tauri/src/adhoc_meetings_watcher.rs +1 -3
  235. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +40 -6
  236. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +4 -2
  237. package/corpus/templates/clips/desktop/src-tauri/src/meetings_watcher.rs +3 -5
  238. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +23 -19
  239. package/corpus/templates/clips/desktop/src-tauri/src/shortcuts.rs +3 -3
  240. package/corpus/templates/clips/desktop/src-tauri/src/silence_detector.rs +0 -1
  241. package/corpus/templates/clips/desktop/src-tauri/src/state.rs +5 -0
  242. package/corpus/templates/clips/desktop/src-tauri/src/tray.rs +18 -6
  243. package/corpus/templates/clips/server/lib/recording-upload-state.ts +63 -0
  244. package/corpus/templates/clips/server/lib/video-storage.ts +4 -0
  245. package/corpus/templates/clips/server/routes/api/recordings/[recordingId]/thumbnail.post.ts +19 -13
  246. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +40 -1
  247. package/corpus/templates/content/.agents/skills/actions/SKILL.md +5 -0
  248. package/corpus/templates/content/.agents/skills/real-time-sync/SKILL.md +1 -1
  249. package/corpus/templates/content/.agents/skills/security/SKILL.md +7 -0
  250. package/corpus/templates/content/.agents/skills/self-modifying-code/SKILL.md +20 -2
  251. package/corpus/templates/content/.agents/skills/storing-data/SKILL.md +5 -1
  252. package/corpus/templates/content/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  253. package/corpus/templates/content/AGENTS.md +4 -0
  254. package/corpus/templates/content/actions/_batch-utils.ts +8 -0
  255. package/corpus/templates/content/actions/_builder-cms-read-client.ts +7 -5
  256. package/corpus/templates/content/actions/_database-source-utils.ts +776 -319
  257. package/corpus/templates/content/actions/_database-utils.ts +6 -1
  258. package/corpus/templates/content/actions/_property-utils.ts +168 -0
  259. package/corpus/templates/content/actions/add-content-database-source-field-property.ts +19 -12
  260. package/corpus/templates/content/actions/bind-content-database-source-field.ts +19 -12
  261. package/corpus/templates/content/actions/delete-document.ts +9 -13
  262. package/corpus/templates/content/actions/refresh-content-database-source.ts +5 -5
  263. package/corpus/templates/content/app/components/editor/body-hydration.ts +35 -11
  264. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +47 -5
  265. package/corpus/templates/content/app/hooks/use-documents.ts +8 -2
  266. package/corpus/templates/content/app/routes/_app.settings.tsx +2 -2
  267. package/corpus/templates/content/app/routes/_app.team.tsx +1 -1
  268. package/corpus/templates/content/changelog/2026-07-08-builder-source-sync-now-completes-reliably-on-hosted-databases.md +6 -0
  269. package/corpus/templates/content/changelog/2026-07-08-fixed-builder-database-sync-so-large-sources-continue-past-t.md +6 -0
  270. package/corpus/templates/content/server/plugins/db.ts +19 -0
  271. package/corpus/templates/design/.agents/skills/actions/SKILL.md +5 -0
  272. package/corpus/templates/design/.agents/skills/security/SKILL.md +7 -0
  273. package/corpus/templates/design/.agents/skills/self-modifying-code/SKILL.md +20 -2
  274. package/corpus/templates/design/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  275. package/corpus/templates/design/AGENTS.md +4 -0
  276. package/corpus/templates/design/actions/take-design-screenshot.ts +12 -9
  277. package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +57 -13
  278. package/corpus/templates/design/app/routes/team.tsx +1 -1
  279. package/corpus/templates/design/changelog/2026-07-08-local-images-added-to-designs-now-upload-to-file-storage-ins.md +6 -0
  280. package/corpus/templates/dispatch/.agents/skills/actions/SKILL.md +5 -0
  281. package/corpus/templates/dispatch/.agents/skills/security/SKILL.md +7 -0
  282. package/corpus/templates/dispatch/.agents/skills/self-modifying-code/SKILL.md +20 -2
  283. package/corpus/templates/dispatch/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  284. package/corpus/templates/dispatch/AGENTS.md +4 -0
  285. package/corpus/templates/dispatch/app/hooks/use-navigation-state.ts +1 -1
  286. package/corpus/templates/dispatch/app/routes/settings.tsx +2 -2
  287. package/corpus/templates/dispatch/app/routes/team.tsx +1 -1
  288. package/corpus/templates/forms/.agents/skills/actions/SKILL.md +5 -0
  289. package/corpus/templates/forms/.agents/skills/real-time-sync/SKILL.md +1 -1
  290. package/corpus/templates/forms/.agents/skills/security/SKILL.md +7 -0
  291. package/corpus/templates/forms/.agents/skills/self-modifying-code/SKILL.md +20 -2
  292. package/corpus/templates/forms/.agents/skills/storing-data/SKILL.md +5 -1
  293. package/corpus/templates/forms/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  294. package/corpus/templates/forms/AGENTS.md +4 -0
  295. package/corpus/templates/forms/app/routes/_app.settings.tsx +2 -2
  296. package/corpus/templates/forms/app/routes/_app.team.tsx +1 -1
  297. package/corpus/templates/forms/shared/navigation.ts +1 -1
  298. package/corpus/templates/macros/.agents/skills/security/SKILL.md +7 -0
  299. package/corpus/templates/macros/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  300. package/corpus/templates/macros/AGENTS.md +4 -0
  301. package/corpus/templates/macros/app/routes/settings.tsx +2 -2
  302. package/corpus/templates/macros/app/routes/team.tsx +1 -1
  303. package/corpus/templates/mail/.agents/skills/actions/SKILL.md +5 -0
  304. package/corpus/templates/mail/.agents/skills/email-drafts/SKILL.md +1 -1
  305. package/corpus/templates/mail/.agents/skills/real-time-sync/SKILL.md +1 -1
  306. package/corpus/templates/mail/.agents/skills/security/SKILL.md +7 -0
  307. package/corpus/templates/mail/.agents/skills/self-modifying-code/SKILL.md +20 -2
  308. package/corpus/templates/mail/.agents/skills/storing-data/SKILL.md +5 -1
  309. package/corpus/templates/mail/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  310. package/corpus/templates/mail/AGENTS.md +4 -0
  311. package/corpus/templates/mail/changelog/2026-07-08-mail-attachments-in-hosted-environments-now-require-file-sto.md +6 -0
  312. package/corpus/templates/mail/server/handlers/media.ts +26 -1
  313. package/corpus/templates/mail/server/lib/outgoing-email.ts +24 -1
  314. package/corpus/templates/mail/server/lib/upload-store.ts +2 -1
  315. package/corpus/templates/plan/.agents/skills/actions/SKILL.md +5 -0
  316. package/corpus/templates/plan/.agents/skills/adding-a-feature/SKILL.md +5 -0
  317. package/corpus/templates/plan/.agents/skills/real-time-sync/SKILL.md +1 -1
  318. package/corpus/templates/plan/.agents/skills/security/SKILL.md +7 -0
  319. package/corpus/templates/plan/.agents/skills/self-modifying-code/SKILL.md +20 -2
  320. package/corpus/templates/plan/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  321. package/corpus/templates/plan/AGENTS.md +4 -0
  322. package/corpus/templates/plan/app/hooks/use-navigation-state.ts +1 -1
  323. package/corpus/templates/plan/app/routes/settings.tsx +2 -2
  324. package/corpus/templates/plan/app/routes/team.tsx +1 -1
  325. package/corpus/templates/plan/changelog/2026-07-08-hosted-plan-images-now-require-connected-storage.md +6 -0
  326. package/corpus/templates/plan/server/lib/plan-assets.ts +33 -4
  327. package/corpus/templates/slides/.agents/skills/actions/SKILL.md +5 -0
  328. package/corpus/templates/slides/.agents/skills/security/SKILL.md +7 -0
  329. package/corpus/templates/slides/.agents/skills/self-modifying-code/SKILL.md +20 -2
  330. package/corpus/templates/slides/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  331. package/corpus/templates/slides/AGENTS.md +4 -0
  332. package/corpus/templates/slides/actions/generate-image-api.ts +15 -3
  333. package/corpus/templates/slides/app/routes/settings.tsx +2 -2
  334. package/corpus/templates/slides/app/routes/team.tsx +1 -1
  335. package/corpus/templates/slides/changelog/2026-07-08-generated-slide-images-now-return-hosted-file-storage-urls-i.md +6 -0
  336. package/corpus/templates/slides/shared/api.ts +1 -1
  337. package/corpus/templates/videos/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  338. package/corpus/templates/voice/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  339. package/dist/agent/production-agent.d.ts +5 -1
  340. package/dist/agent/production-agent.d.ts.map +1 -1
  341. package/dist/agent/production-agent.js +112 -42
  342. package/dist/agent/production-agent.js.map +1 -1
  343. package/dist/agent/tool-search.d.ts +2 -0
  344. package/dist/agent/tool-search.d.ts.map +1 -1
  345. package/dist/agent/tool-search.js +60 -4
  346. package/dist/agent/tool-search.js.map +1 -1
  347. package/dist/application-state/store.d.ts.map +1 -1
  348. package/dist/application-state/store.js +8 -2
  349. package/dist/application-state/store.js.map +1 -1
  350. package/dist/cli/index.js +19 -0
  351. package/dist/cli/index.js.map +1 -1
  352. package/dist/cli/upgrade.d.ts +100 -0
  353. package/dist/cli/upgrade.d.ts.map +1 -0
  354. package/dist/cli/upgrade.js +678 -0
  355. package/dist/cli/upgrade.js.map +1 -0
  356. package/dist/client/AssistantChat.d.ts.map +1 -1
  357. package/dist/client/AssistantChat.js +25 -14
  358. package/dist/client/AssistantChat.js.map +1 -1
  359. package/dist/client/HighlightedCodeBlock.d.ts +2 -0
  360. package/dist/client/HighlightedCodeBlock.d.ts.map +1 -1
  361. package/dist/client/HighlightedCodeBlock.js +10 -1
  362. package/dist/client/HighlightedCodeBlock.js.map +1 -1
  363. package/dist/client/PoweredByBadge.d.ts +1 -1
  364. package/dist/client/PoweredByBadge.d.ts.map +1 -1
  365. package/dist/client/PoweredByBadge.js +3 -9
  366. package/dist/client/PoweredByBadge.js.map +1 -1
  367. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  368. package/dist/client/agent-chat-adapter.js +60 -13
  369. package/dist/client/agent-chat-adapter.js.map +1 -1
  370. package/dist/client/chat/message-components.d.ts.map +1 -1
  371. package/dist/client/chat/message-components.js +61 -8
  372. package/dist/client/chat/message-components.js.map +1 -1
  373. package/dist/client/chat/tool-call-display.d.ts +12 -0
  374. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  375. package/dist/client/chat/tool-call-display.js +136 -42
  376. package/dist/client/chat/tool-call-display.js.map +1 -1
  377. package/dist/client/chat/widgets/DataTableWidget.d.ts.map +1 -1
  378. package/dist/client/chat/widgets/DataTableWidget.js +19 -2
  379. package/dist/client/chat/widgets/DataTableWidget.js.map +1 -1
  380. package/dist/client/code-agent-chat-adapter.js +2 -9
  381. package/dist/client/code-agent-chat-adapter.js.map +1 -1
  382. package/dist/client/db-admin/TableEditor.d.ts.map +1 -1
  383. package/dist/client/db-admin/TableEditor.js +19 -2
  384. package/dist/client/db-admin/TableEditor.js.map +1 -1
  385. package/dist/client/db-admin/export-utils.d.ts +2 -0
  386. package/dist/client/db-admin/export-utils.d.ts.map +1 -1
  387. package/dist/client/db-admin/export-utils.js +11 -3
  388. package/dist/client/db-admin/export-utils.js.map +1 -1
  389. package/dist/client/db-admin/useAgentSync.d.ts.map +1 -1
  390. package/dist/client/db-admin/useAgentSync.js +63 -0
  391. package/dist/client/db-admin/useAgentSync.js.map +1 -1
  392. package/dist/client/error-capture.d.ts.map +1 -1
  393. package/dist/client/error-capture.js +41 -7
  394. package/dist/client/error-capture.js.map +1 -1
  395. package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
  396. package/dist/client/extensions/EmbeddedExtension.js +3 -1
  397. package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
  398. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
  399. package/dist/client/extensions/ExtensionViewer.js +32 -5
  400. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  401. package/dist/client/extensions/InlineExtensionFrame.d.ts.map +1 -1
  402. package/dist/client/extensions/InlineExtensionFrame.js +3 -1
  403. package/dist/client/extensions/InlineExtensionFrame.js.map +1 -1
  404. package/dist/client/extensions/portable-extension.d.ts.map +1 -1
  405. package/dist/client/extensions/portable-extension.js +1 -0
  406. package/dist/client/extensions/portable-extension.js.map +1 -1
  407. package/dist/client/org/OrgSwitcher.d.ts +1 -1
  408. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  409. package/dist/client/org/OrgSwitcher.js +11 -6
  410. package/dist/client/org/OrgSwitcher.js.map +1 -1
  411. package/dist/client/org/TeamPage.d.ts.map +1 -1
  412. package/dist/client/org/TeamPage.js +5 -5
  413. package/dist/client/org/TeamPage.js.map +1 -1
  414. package/dist/client/session-replay.d.ts +0 -8
  415. package/dist/client/session-replay.d.ts.map +1 -1
  416. package/dist/client/session-replay.js +3 -80
  417. package/dist/client/session-replay.js.map +1 -1
  418. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  419. package/dist/client/settings/SettingsPanel.js +89 -33
  420. package/dist/client/settings/SettingsPanel.js.map +1 -1
  421. package/dist/client/settings/SettingsSection.d.ts +19 -4
  422. package/dist/client/settings/SettingsSection.d.ts.map +1 -1
  423. package/dist/client/settings/SettingsSection.js +33 -4
  424. package/dist/client/settings/SettingsSection.js.map +1 -1
  425. package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -1
  426. package/dist/client/settings/SettingsTabsPage.js +21 -10
  427. package/dist/client/settings/SettingsTabsPage.js.map +1 -1
  428. package/dist/client/sse-event-processor.d.ts +9 -0
  429. package/dist/client/sse-event-processor.d.ts.map +1 -1
  430. package/dist/client/sse-event-processor.js +20 -2
  431. package/dist/client/sse-event-processor.js.map +1 -1
  432. package/dist/db-admin/agent-tools.d.ts.map +1 -1
  433. package/dist/db-admin/agent-tools.js +7 -2
  434. package/dist/db-admin/agent-tools.js.map +1 -1
  435. package/dist/db-admin/operations.d.ts.map +1 -1
  436. package/dist/db-admin/operations.js +90 -4
  437. package/dist/db-admin/operations.js.map +1 -1
  438. package/dist/db-admin/routes.d.ts.map +1 -1
  439. package/dist/db-admin/routes.js +1 -0
  440. package/dist/db-admin/routes.js.map +1 -1
  441. package/dist/db-admin/types.d.ts +4 -0
  442. package/dist/db-admin/types.d.ts.map +1 -1
  443. package/dist/db-admin/types.js.map +1 -1
  444. package/dist/extensions/actions.d.ts.map +1 -1
  445. package/dist/extensions/actions.js +85 -5
  446. package/dist/extensions/actions.js.map +1 -1
  447. package/dist/extensions/html-shell.d.ts +5 -4
  448. package/dist/extensions/html-shell.d.ts.map +1 -1
  449. package/dist/extensions/html-shell.js.map +1 -1
  450. package/dist/extensions/routes.d.ts.map +1 -1
  451. package/dist/extensions/routes.js +8 -0
  452. package/dist/extensions/routes.js.map +1 -1
  453. package/dist/navigation/index.d.ts +1 -1
  454. package/dist/navigation/index.d.ts.map +1 -1
  455. package/dist/navigation/index.js +1 -1
  456. package/dist/navigation/index.js.map +1 -1
  457. package/dist/notifications/channels.d.ts +8 -3
  458. package/dist/notifications/channels.d.ts.map +1 -1
  459. package/dist/notifications/channels.js +61 -22
  460. package/dist/notifications/channels.js.map +1 -1
  461. package/dist/notifications/registry.d.ts.map +1 -1
  462. package/dist/notifications/registry.js +14 -3
  463. package/dist/notifications/registry.js.map +1 -1
  464. package/dist/notifications/types.d.ts +4 -1
  465. package/dist/notifications/types.d.ts.map +1 -1
  466. package/dist/notifications/types.js.map +1 -1
  467. package/dist/resources/handlers.d.ts +5 -0
  468. package/dist/resources/handlers.d.ts.map +1 -1
  469. package/dist/resources/handlers.js +9 -8
  470. package/dist/resources/handlers.js.map +1 -1
  471. package/dist/server/agent-chat-plugin.d.ts +5 -1
  472. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  473. package/dist/server/agent-chat-plugin.js +2 -2
  474. package/dist/server/agent-chat-plugin.js.map +1 -1
  475. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  476. package/dist/server/poll.d.ts +12 -4
  477. package/dist/server/poll.d.ts.map +1 -1
  478. package/dist/server/poll.js +236 -9
  479. package/dist/server/poll.js.map +1 -1
  480. package/dist/server/request-context.d.ts +7 -0
  481. package/dist/server/request-context.d.ts.map +1 -1
  482. package/dist/server/request-context.js.map +1 -1
  483. package/dist/styles/agent-conversation.css +1 -1
  484. package/dist/styles/agent-native.css +27 -0
  485. package/dist/templates/default/.agents/skills/actions/SKILL.md +5 -0
  486. package/dist/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
  487. package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
  488. package/dist/templates/default/.agents/skills/security/SKILL.md +7 -0
  489. package/dist/templates/default/.agents/skills/self-modifying-code/SKILL.md +20 -2
  490. package/dist/templates/default/.agents/skills/storing-data/SKILL.md +5 -1
  491. package/dist/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  492. package/dist/templates/default/AGENTS.md +14 -5
  493. package/dist/templates/default/package.json +2 -1
  494. package/dist/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  495. package/dist/templates/headless/AGENTS.md +13 -3
  496. package/dist/templates/headless/package.json +1 -0
  497. package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +5 -0
  498. package/dist/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
  499. package/dist/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +4 -0
  500. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -0
  501. package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +4 -0
  502. package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
  503. package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +7 -0
  504. package/dist/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +20 -2
  505. package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +5 -1
  506. package/dist/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  507. package/dist/templates/workspace-core/AGENTS.md +7 -1
  508. package/dist/templates/workspace-root/AGENTS.md +17 -5
  509. package/dist/templates/workspace-root/package.json +1 -0
  510. package/docs/content/faq.mdx +17 -0
  511. package/docs/content/notifications.mdx +12 -6
  512. package/package.json +2 -2
  513. package/src/templates/default/.agents/skills/actions/SKILL.md +5 -0
  514. package/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
  515. package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
  516. package/src/templates/default/.agents/skills/security/SKILL.md +7 -0
  517. package/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +20 -2
  518. package/src/templates/default/.agents/skills/storing-data/SKILL.md +5 -1
  519. package/src/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  520. package/src/templates/default/AGENTS.md +14 -5
  521. package/src/templates/default/package.json +2 -1
  522. package/src/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  523. package/src/templates/headless/AGENTS.md +13 -3
  524. package/src/templates/headless/package.json +1 -0
  525. package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +5 -0
  526. package/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
  527. package/src/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +4 -0
  528. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -0
  529. package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +4 -0
  530. package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
  531. package/src/templates/workspace-core/.agents/skills/security/SKILL.md +7 -0
  532. package/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +20 -2
  533. package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +5 -1
  534. package/src/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
  535. package/src/templates/workspace-core/AGENTS.md +7 -1
  536. package/src/templates/workspace-root/AGENTS.md +17 -5
  537. package/src/templates/workspace-root/package.json +1 -0
  538. package/corpus/templates/analytics/changelog/2026-07-08-session-replay-clamps-ultra-wide-viewports-while-keeping-the.md +0 -6
@@ -13,10 +13,15 @@
13
13
  * `onNavigate(table)` then DELETEs the key so it fires exactly once.
14
14
  */
15
15
  import { useEffect, useRef } from "react";
16
+ import { removeAgentChatContextItem, setAgentChatContextItem, } from "../agent-chat.js";
16
17
  import { agentNativePath } from "../api-path.js";
18
+ import { deleteClientAppState, readClientAppState, setClientAppState, } from "../application-state.js";
17
19
  const NAVIGATION_PATH = agentNativePath("/_agent-native/application-state/navigation");
18
20
  const NAVIGATE_PATH = agentNativePath("/_agent-native/application-state/navigate");
19
21
  const POLL_INTERVAL_MS = 1500;
22
+ const TABLE_CONTEXT_KEY = "database-selected-table";
23
+ const SELECTED_OBJECT_STATE_KEY = "selected-object";
24
+ const SELECTED_OBJECT_SOURCE_FIELD = "__agentNativeSelectedObjectSource";
20
25
  let cachedSource = null;
21
26
  function requestSource() {
22
27
  if (typeof window === "undefined")
@@ -47,6 +52,23 @@ function headers(extra) {
47
52
  h["X-Request-Source"] = source;
48
53
  return h;
49
54
  }
55
+ async function deleteSelectedObjectIfOwned(source) {
56
+ if (!source)
57
+ return;
58
+ try {
59
+ const current = await readClientAppState(SELECTED_OBJECT_STATE_KEY);
60
+ if (current?.[SELECTED_OBJECT_SOURCE_FIELD] !== source)
61
+ return;
62
+ await deleteClientAppState(SELECTED_OBJECT_STATE_KEY, {
63
+ keepalive: true,
64
+ requestSource: source,
65
+ });
66
+ }
67
+ catch {
68
+ // Best effort only; stale selected-object context is less harmful than
69
+ // clearing a selection owned by another tab.
70
+ }
71
+ }
50
72
  /**
51
73
  * Write the current database-admin view to application state whenever the
52
74
  * selected table or mode changes, so the agent always knows what the user is
@@ -65,6 +87,47 @@ export function useDbAdminAgentSync({ table, mode, enabled = true, }) {
65
87
  body: JSON.stringify(state),
66
88
  }).catch(() => { });
67
89
  }, [enabled, table, mode]);
90
+ useEffect(() => {
91
+ if (!enabled)
92
+ return;
93
+ const source = requestSource();
94
+ if (!table) {
95
+ removeAgentChatContextItem({
96
+ key: TABLE_CONTEXT_KEY,
97
+ openSidebar: false,
98
+ });
99
+ deleteSelectedObjectIfOwned(source);
100
+ return;
101
+ }
102
+ const selection = {
103
+ type: "database-table",
104
+ table,
105
+ mode,
106
+ [SELECTED_OBJECT_SOURCE_FIELD]: source,
107
+ };
108
+ setAgentChatContextItem({
109
+ key: TABLE_CONTEXT_KEY,
110
+ title: `Table: ${table}`,
111
+ context: [
112
+ `The user currently has this database table selected: ${table}.`,
113
+ `Database admin mode: ${mode}`,
114
+ "Use the database admin actions and current-screen context to inspect rows, schema, or run SQL against this table.",
115
+ ].join("\n"),
116
+ openSidebar: false,
117
+ focus: false,
118
+ });
119
+ setClientAppState(SELECTED_OBJECT_STATE_KEY, selection, {
120
+ keepalive: true,
121
+ requestSource: source,
122
+ }).catch(() => { });
123
+ return () => {
124
+ removeAgentChatContextItem({
125
+ key: TABLE_CONTEXT_KEY,
126
+ openSidebar: false,
127
+ });
128
+ deleteSelectedObjectIfOwned(source);
129
+ };
130
+ }, [enabled, table, mode]);
68
131
  }
69
132
  /**
70
133
  * Poll the one-shot `navigate` app-state key. When the agent requests a jump to
@@ -1 +1 @@
1
- {"version":3,"file":"useAgentSync.js","sourceRoot":"","sources":["../../../src/client/db-admin/useAgentSync.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Two-way navigation sync between the database admin UI and the agent.\n *\n * (a) `useDbAdminAgentSync` writes the current view into application state\n * under the `navigation` key, so the agent's `<current-screen>` context\n * knows which table/mode is open. Mirrors the template\n * `use-navigation-state` write mechanism (PUT to the app-state route with a\n * request-source header), but talks to the route directly since core has no\n * template `TAB_ID`.\n *\n * (b) `useNavigateConsumer` short-polls the one-shot `navigate` app-state key.\n * When the agent sets `{ view: \"database\", table }`, the consumer invokes\n * `onNavigate(table)` then DELETEs the key so it fires exactly once.\n */\nimport { useEffect, useRef } from \"react\";\n\nimport { agentNativePath } from \"../api-path.js\";\n\nconst NAVIGATION_PATH = agentNativePath(\n \"/_agent-native/application-state/navigation\",\n);\nconst NAVIGATE_PATH = agentNativePath(\n \"/_agent-native/application-state/navigate\",\n);\n\nconst POLL_INTERVAL_MS = 1500;\n\nlet cachedSource: string | null = null;\n\nfunction requestSource(): string | undefined {\n if (typeof window === \"undefined\") return undefined;\n if (cachedSource) return cachedSource;\n try {\n const existing = window.sessionStorage.getItem(\"agentnative.tabId\");\n if (existing) {\n cachedSource = existing;\n return existing;\n }\n const generated =\n typeof crypto !== \"undefined\" && \"randomUUID\" in crypto\n ? crypto.randomUUID()\n : `tab-${Math.random().toString(36).slice(2)}`;\n window.sessionStorage.setItem(\"agentnative.tabId\", generated);\n cachedSource = generated;\n return generated;\n } catch {\n return undefined;\n }\n}\n\nfunction headers(extra?: Record<string, string>): Record<string, string> {\n const h: Record<string, string> = { ...extra };\n const source = requestSource();\n if (source) h[\"X-Request-Source\"] = source;\n return h;\n}\n\nexport interface DbAdminNavigationState {\n view: \"database\";\n table: string | null;\n mode: \"table\" | \"sql\";\n}\n\nexport interface UseDbAdminAgentSyncArgs {\n table: string | null;\n mode: \"table\" | \"sql\";\n enabled?: boolean;\n}\n\n/**\n * Write the current database-admin view to application state whenever the\n * selected table or mode changes, so the agent always knows what the user is\n * looking at.\n */\nexport function useDbAdminAgentSync({\n table,\n mode,\n enabled = true,\n}: UseDbAdminAgentSyncArgs): void {\n useEffect(() => {\n if (!enabled) return;\n const state: DbAdminNavigationState = { view: \"database\", table, mode };\n fetch(NAVIGATION_PATH, {\n method: \"PUT\",\n keepalive: true,\n credentials: \"include\",\n headers: headers({ \"Content-Type\": \"application/json\" }),\n body: JSON.stringify(state),\n }).catch(() => {});\n }, [enabled, table, mode]);\n}\n\ninterface NavigateCommand {\n view?: string;\n table?: string | null;\n}\n\n/**\n * Poll the one-shot `navigate` app-state key. When the agent requests a jump to\n * a database table, invoke `onNavigate(table)` then clear the key so it does\n * not replay on the next poll.\n */\nexport function useNavigateConsumer(\n onNavigate: (table: string) => void,\n enabled = true,\n): void {\n const handlerRef = useRef(onNavigate);\n handlerRef.current = onNavigate;\n\n useEffect(() => {\n if (!enabled) return;\n let active = true;\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n const tick = async () => {\n if (!active) return;\n try {\n const res = await fetch(NAVIGATE_PATH, {\n method: \"GET\",\n credentials: \"include\",\n headers: headers(),\n });\n if (active && res.ok) {\n const data = (await res.json()) as NavigateCommand | null;\n if (\n data &&\n data.view === \"database\" &&\n typeof data.table === \"string\" &&\n data.table\n ) {\n const target = data.table;\n // Clear the one-shot command before acting so it fires once.\n fetch(NAVIGATE_PATH, {\n method: \"DELETE\",\n credentials: \"include\",\n headers: headers({ \"X-Agent-Native-CSRF\": \"1\" }),\n }).catch(() => {});\n handlerRef.current(target);\n }\n }\n } catch {\n // Ignore transient errors; the next tick retries.\n } finally {\n if (active) timer = setTimeout(tick, POLL_INTERVAL_MS);\n }\n };\n\n timer = setTimeout(tick, POLL_INTERVAL_MS);\n return () => {\n active = false;\n if (timer) clearTimeout(timer);\n };\n }, [enabled]);\n}\n"]}
1
+ {"version":3,"file":"useAgentSync.js","sourceRoot":"","sources":["../../../src/client/db-admin/useAgentSync.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Two-way navigation sync between the database admin UI and the agent.\n *\n * (a) `useDbAdminAgentSync` writes the current view into application state\n * under the `navigation` key, so the agent's `<current-screen>` context\n * knows which table/mode is open. Mirrors the template\n * `use-navigation-state` write mechanism (PUT to the app-state route with a\n * request-source header), but talks to the route directly since core has no\n * template `TAB_ID`.\n *\n * (b) `useNavigateConsumer` short-polls the one-shot `navigate` app-state key.\n * When the agent sets `{ view: \"database\", table }`, the consumer invokes\n * `onNavigate(table)` then DELETEs the key so it fires exactly once.\n */\nimport { useEffect, useRef } from \"react\";\n\nimport {\n removeAgentChatContextItem,\n setAgentChatContextItem,\n} from \"../agent-chat.js\";\nimport { agentNativePath } from \"../api-path.js\";\nimport {\n deleteClientAppState,\n readClientAppState,\n setClientAppState,\n} from \"../application-state.js\";\n\nconst NAVIGATION_PATH = agentNativePath(\n \"/_agent-native/application-state/navigation\",\n);\nconst NAVIGATE_PATH = agentNativePath(\n \"/_agent-native/application-state/navigate\",\n);\n\nconst POLL_INTERVAL_MS = 1500;\nconst TABLE_CONTEXT_KEY = \"database-selected-table\";\nconst SELECTED_OBJECT_STATE_KEY = \"selected-object\";\nconst SELECTED_OBJECT_SOURCE_FIELD = \"__agentNativeSelectedObjectSource\";\n\nlet cachedSource: string | null = null;\n\nfunction requestSource(): string | undefined {\n if (typeof window === \"undefined\") return undefined;\n if (cachedSource) return cachedSource;\n try {\n const existing = window.sessionStorage.getItem(\"agentnative.tabId\");\n if (existing) {\n cachedSource = existing;\n return existing;\n }\n const generated =\n typeof crypto !== \"undefined\" && \"randomUUID\" in crypto\n ? crypto.randomUUID()\n : `tab-${Math.random().toString(36).slice(2)}`;\n window.sessionStorage.setItem(\"agentnative.tabId\", generated);\n cachedSource = generated;\n return generated;\n } catch {\n return undefined;\n }\n}\n\nfunction headers(extra?: Record<string, string>): Record<string, string> {\n const h: Record<string, string> = { ...extra };\n const source = requestSource();\n if (source) h[\"X-Request-Source\"] = source;\n return h;\n}\n\nasync function deleteSelectedObjectIfOwned(source: string | undefined) {\n if (!source) return;\n try {\n const current = await readClientAppState<Record<string, unknown>>(\n SELECTED_OBJECT_STATE_KEY,\n );\n if (current?.[SELECTED_OBJECT_SOURCE_FIELD] !== source) return;\n await deleteClientAppState(SELECTED_OBJECT_STATE_KEY, {\n keepalive: true,\n requestSource: source,\n });\n } catch {\n // Best effort only; stale selected-object context is less harmful than\n // clearing a selection owned by another tab.\n }\n}\n\nexport interface DbAdminNavigationState {\n view: \"database\";\n table: string | null;\n mode: \"table\" | \"sql\";\n}\n\nexport interface UseDbAdminAgentSyncArgs {\n table: string | null;\n mode: \"table\" | \"sql\";\n enabled?: boolean;\n}\n\n/**\n * Write the current database-admin view to application state whenever the\n * selected table or mode changes, so the agent always knows what the user is\n * looking at.\n */\nexport function useDbAdminAgentSync({\n table,\n mode,\n enabled = true,\n}: UseDbAdminAgentSyncArgs): void {\n useEffect(() => {\n if (!enabled) return;\n const state: DbAdminNavigationState = { view: \"database\", table, mode };\n fetch(NAVIGATION_PATH, {\n method: \"PUT\",\n keepalive: true,\n credentials: \"include\",\n headers: headers({ \"Content-Type\": \"application/json\" }),\n body: JSON.stringify(state),\n }).catch(() => {});\n }, [enabled, table, mode]);\n\n useEffect(() => {\n if (!enabled) return;\n const source = requestSource();\n if (!table) {\n removeAgentChatContextItem({\n key: TABLE_CONTEXT_KEY,\n openSidebar: false,\n });\n deleteSelectedObjectIfOwned(source);\n return;\n }\n\n const selection = {\n type: \"database-table\",\n table,\n mode,\n [SELECTED_OBJECT_SOURCE_FIELD]: source,\n };\n setAgentChatContextItem({\n key: TABLE_CONTEXT_KEY,\n title: `Table: ${table}`,\n context: [\n `The user currently has this database table selected: ${table}.`,\n `Database admin mode: ${mode}`,\n \"Use the database admin actions and current-screen context to inspect rows, schema, or run SQL against this table.\",\n ].join(\"\\n\"),\n openSidebar: false,\n focus: false,\n });\n setClientAppState(SELECTED_OBJECT_STATE_KEY, selection, {\n keepalive: true,\n requestSource: source,\n }).catch(() => {});\n\n return () => {\n removeAgentChatContextItem({\n key: TABLE_CONTEXT_KEY,\n openSidebar: false,\n });\n deleteSelectedObjectIfOwned(source);\n };\n }, [enabled, table, mode]);\n}\n\ninterface NavigateCommand {\n view?: string;\n table?: string | null;\n}\n\n/**\n * Poll the one-shot `navigate` app-state key. When the agent requests a jump to\n * a database table, invoke `onNavigate(table)` then clear the key so it does\n * not replay on the next poll.\n */\nexport function useNavigateConsumer(\n onNavigate: (table: string) => void,\n enabled = true,\n): void {\n const handlerRef = useRef(onNavigate);\n handlerRef.current = onNavigate;\n\n useEffect(() => {\n if (!enabled) return;\n let active = true;\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n const tick = async () => {\n if (!active) return;\n try {\n const res = await fetch(NAVIGATE_PATH, {\n method: \"GET\",\n credentials: \"include\",\n headers: headers(),\n });\n if (active && res.ok) {\n const data = (await res.json()) as NavigateCommand | null;\n if (\n data &&\n data.view === \"database\" &&\n typeof data.table === \"string\" &&\n data.table\n ) {\n const target = data.table;\n // Clear the one-shot command before acting so it fires once.\n fetch(NAVIGATE_PATH, {\n method: \"DELETE\",\n credentials: \"include\",\n headers: headers({ \"X-Agent-Native-CSRF\": \"1\" }),\n }).catch(() => {});\n handlerRef.current(target);\n }\n }\n } catch {\n // Ignore transient errors; the next tick retries.\n } finally {\n if (active) timer = setTimeout(tick, POLL_INTERVAL_MS);\n }\n };\n\n timer = setTimeout(tick, POLL_INTERVAL_MS);\n return () => {\n active = false;\n if (timer) clearTimeout(timer);\n };\n }, [enabled]);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"error-capture.d.ts","sourceRoot":"","sources":["../../src/client/error-capture.ts"],"names":[],"mappings":"AAyBA,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAE9E,iEAAiE;AACjE,MAAM,WAAW,uBAAuB;IACtC,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IACpE,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,qCAAqC;IACrC,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,cAAc,CAAC;IACtB,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,mBAAmB,EAAE,CAAC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,0BAA0B;IACzC,0DAA0D;IAC1D,IAAI,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CAAC;IAC9C,4EAA4E;IAC5E,iBAAiB,CAAC,EAAE,MAAM;QACxB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CAAC;IAC1D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,2DAA2D;IAC3D,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,mDAAmD;IACnD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AA6FD,2EAA2E;AAC3E,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CA2BA;AAmHD,mEAAmE;AACnE,wBAAgB,kBAAkB,CAAC,UAAU,EAAE;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB,GAAG,IAAI,CAgBP;AA4GD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,uBAA4B,GACpC,IAAI,CAcN;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,KAAK,GAAE,cAAuB,GAC7B,IAAI,CAYN;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,0BAA0B,GAClC,MAAM,IAAI,CA8FZ;AAED,wBAAgB,uBAAuB,IAAI,OAAO,CAEjD"}
1
+ {"version":3,"file":"error-capture.d.ts","sourceRoot":"","sources":["../../src/client/error-capture.ts"],"names":[],"mappings":"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"}
@@ -191,6 +191,42 @@ function firstStackLine(stack) {
191
191
  function signatureOf(type, message, stack) {
192
192
  return `${type}|${message}|${firstStackLine(stack)}`;
193
193
  }
194
+ function normalizeGlobalErrorEvent(event) {
195
+ const error = event?.error;
196
+ const normalized = error
197
+ ? normalizeCapturedError(error)
198
+ : {
199
+ type: "Error",
200
+ message: String(event?.message ?? "Uncaught error"),
201
+ };
202
+ if (!normalized.stack && event?.filename) {
203
+ const line = event.lineno ?? 0;
204
+ const col = event.colno ?? 0;
205
+ normalized.stack = `at ${event.filename}:${line}:${col}`;
206
+ }
207
+ return normalized;
208
+ }
209
+ function shouldIgnoreAutoCapturedError(normalized) {
210
+ const message = (normalized.message || "").trim();
211
+ const stack = normalized.stack || "";
212
+ if (/^ResizeObserver loop (?:limit exceeded|completed with undelivered notifications\.?)$/i.test(message)) {
213
+ return true;
214
+ }
215
+ if (normalized.type === "InvalidStateError" &&
216
+ /^Transition was aborted because of invalid state$/i.test(message)) {
217
+ return true;
218
+ }
219
+ if (/^This script should only be loaded in a browser extension\.?$/i.test(message)) {
220
+ return true;
221
+ }
222
+ const hasExtensionFrame = /\b(?:chrome|moz|safari|webkit)-extension:\/\//i.test(stack) ||
223
+ /\binjectScriptAdjust\.js\b/i.test(stack);
224
+ if (hasExtensionFrame &&
225
+ /^(?:TypeError:\s*)?Failed to fetch$/i.test(message)) {
226
+ return true;
227
+ }
228
+ return false;
229
+ }
194
230
  function shouldDedupe(runtime, signature) {
195
231
  const now = Date.now();
196
232
  const windowMs = runtime.config.dedupeWindowMs;
@@ -375,13 +411,9 @@ export function installErrorCapture(options) {
375
411
  if (runtime.config.captureGlobalErrors) {
376
412
  const onError = (event) => {
377
413
  try {
378
- const error = event?.error;
379
- const normalized = error
380
- ? normalizeCapturedError(error)
381
- : {
382
- type: "Error",
383
- message: String(event?.message ?? "Uncaught error"),
384
- };
414
+ const normalized = normalizeGlobalErrorEvent(event);
415
+ if (shouldIgnoreAutoCapturedError(normalized))
416
+ return;
385
417
  // Global errors are already logged by the session replay recorder, so
386
418
  // don't re-emit them onto the replay timeline (avoid double-counting).
387
419
  dispatch(runtime, buildEvent(runtime, normalized, {
@@ -404,6 +436,8 @@ export function installErrorCapture(options) {
404
436
  if (!normalized.type || normalized.type === "Error") {
405
437
  normalized.type = "UnhandledRejection";
406
438
  }
439
+ if (shouldIgnoreAutoCapturedError(normalized))
440
+ return;
407
441
  dispatch(runtime, buildEvent(runtime, normalized, {
408
442
  handled: false,
409
443
  level: "error",
@@ -1 +1 @@
1
- {"version":3,"file":"error-capture.js","sourceRoot":"","sources":["../../src/client/error-capture.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * First-party, Sentry-style browser error capture for the Agent Native\n * analytics SDK.\n *\n * Two responsibilities:\n * 1. Automatic capture of uncaught exceptions (`window.onerror`) and\n * unhandled promise rejections (`unhandledrejection`).\n * 2. A documented manual API — `captureException(error, context?)` and\n * `captureMessage(message, level?)` — mirroring Sentry's ergonomics.\n *\n * Captured exceptions are handed to a `send` callback (wired by\n * `configureTracking` to the first-party analytics `/track` ingest as a\n * dedicated `$exception` event) and are tagged with the current analytics\n * session id + session replay id so each error links back to the recording it\n * happened in. Everything here is defensive: capture must never throw back into\n * the host app, so every path is wrapped and failures are swallowed.\n *\n * Stack parsing and fingerprinting are intentionally done authoritatively on\n * the server (see the analytics template's `server/lib/error-capture.ts`); the\n * client sends a compact, bounded payload (type/message/raw stack/context) and\n * the server normalizes + groups it. That keeps one tested source of truth for\n * grouping instead of duplicating parser logic across the wire.\n */\nimport { scrubUrl } from \"./url-scrub.js\";\n\nexport type ExceptionLevel = \"fatal\" | \"error\" | \"warning\" | \"info\" | \"debug\";\n\n/** Extra Sentry-style context accepted by `captureException`. */\nexport interface CaptureExceptionContext {\n /** Low-cardinality searchable tags. Values are coerced to strings. */\n tags?: Record<string, string | number | boolean | null | undefined>;\n /** Structured, higher-cardinality detail shown on the event. */\n extra?: Record<string, unknown>;\n /** Severity; defaults to \"error\". */\n level?: ExceptionLevel;\n}\n\nexport interface ExceptionBreadcrumb {\n timestamp: string;\n category: string;\n message: string;\n level?: ExceptionLevel;\n}\n\n/**\n * Compact exception payload emitted to transport. Field names are the wire\n * contract the analytics server ingest reads — keep them stable.\n */\nexport interface CapturedExceptionEvent {\n /** Error class/name, e.g. \"TypeError\". \"Message\" for `captureMessage`. */\n type: string;\n message: string;\n /** Raw (bounded, redacted) stack string; server parses it into frames. */\n stack?: string;\n /** False for uncaught/global errors, true for manually handled ones. */\n handled: boolean;\n level: ExceptionLevel;\n /** ISO timestamp of the occurrence. */\n occurredAt: string;\n url?: string;\n release?: string;\n environment?: string;\n sessionId?: string;\n /** Client session replay id (localStorage) for replay linkage. */\n sessionReplayId?: string;\n anonymousId?: string;\n breadcrumbs: ExceptionBreadcrumb[];\n tags?: Record<string, string>;\n extra?: Record<string, unknown>;\n}\n\nexport interface InstallErrorCaptureOptions {\n /** Transport for a captured exception. Must not throw. */\n send: (event: CapturedExceptionEvent) => void;\n /** Resolve current analytics/session-replay identifiers at capture time. */\n getSessionContext?: () => {\n sessionId?: string;\n anonymousId?: string;\n replayId?: string;\n };\n /**\n * Optional hook to also surface a manual capture on the session replay\n * timeline. Only invoked for manual `captureException`/`captureMessage`;\n * auto-captured global errors are already recorded by the replay recorder.\n */\n emitReplayEvent?: (event: CapturedExceptionEvent) => void;\n release?: string;\n environment?: string;\n /** Auto-capture `window.onerror`. Defaults to true. */\n captureGlobalErrors?: boolean;\n /** Auto-capture `unhandledrejection`. Defaults to true. */\n captureUnhandledRejections?: boolean;\n /** Breadcrumb ring buffer size. Defaults to 20. */\n maxBreadcrumbs?: number;\n /** Dedupe window (ms) for identical signatures. Defaults to 3000. */\n dedupeWindowMs?: number;\n}\n\ninterface ErrorCaptureRuntime {\n installed: boolean;\n config: Required<\n Pick<\n InstallErrorCaptureOptions,\n | \"captureGlobalErrors\"\n | \"captureUnhandledRejections\"\n | \"maxBreadcrumbs\"\n | \"dedupeWindowMs\"\n >\n > &\n Omit<\n InstallErrorCaptureOptions,\n | \"captureGlobalErrors\"\n | \"captureUnhandledRejections\"\n | \"maxBreadcrumbs\"\n | \"dedupeWindowMs\"\n >;\n breadcrumbs: ExceptionBreadcrumb[];\n recentSignatures: Map<string, number>;\n removeHandlers: (() => void) | null;\n navigationInstalled: boolean;\n}\n\nconst MAX_MESSAGE_LENGTH = 1000;\nconst MAX_STACK_LENGTH = 8000;\nconst MAX_TAGS = 30;\nconst MAX_EXTRA_KEYS = 50;\nconst MAX_EXTRA_DEPTH = 4;\nconst MAX_EXTRA_OBJECT_KEYS = 20;\nconst MAX_EXTRA_ARRAY_ITEMS = 20;\nconst MAX_EXTRA_STRING_LENGTH = 2000;\n\nconst ERROR_CAPTURE_STATE_KEY = Symbol.for(\"agent-native.client.errorCapture\");\n\n// Reuse the same credential-looking redaction the replay capture uses so a\n// stack/message that echoes a token never leaves the browser in the clear.\nconst SECRET_KEY_FRAGMENT =\n \"(?:authorization|cookie|set[-_]?cookie|token|secret|password|passwd|pwd|api[-_]?key|apikey|session|credential)\";\nconst BEARER_RE = /\\b(bearer|basic)\\s+[a-z0-9._~+/-]+=*/gi;\nconst UNQUOTED_SECRET_RE = new RegExp(\n `([\"']?)([A-Za-z0-9_$.-]*${SECRET_KEY_FRAGMENT}[A-Za-z0-9_$.-]*)\\\\1(\\\\s*[:=]\\\\s*)([^\"',\\\\s;}\\\\]]+)`,\n \"gi\",\n);\nconst SECRET_KEY_RE = new RegExp(SECRET_KEY_FRAGMENT, \"i\");\n\nfunction redactSecrets(value: string): string {\n return value\n .replace(BEARER_RE, \"$1 <redacted>\")\n .replace(UNQUOTED_SECRET_RE, \"$1$2$1$3<redacted>\");\n}\n\nfunction getRuntime(): ErrorCaptureRuntime {\n const g = globalThis as typeof globalThis & {\n [ERROR_CAPTURE_STATE_KEY]?: ErrorCaptureRuntime;\n };\n if (!g[ERROR_CAPTURE_STATE_KEY]) {\n g[ERROR_CAPTURE_STATE_KEY] = {\n installed: false,\n config: {\n send: () => {},\n captureGlobalErrors: true,\n captureUnhandledRejections: true,\n maxBreadcrumbs: 20,\n dedupeWindowMs: 3000,\n },\n breadcrumbs: [],\n recentSignatures: new Map(),\n removeHandlers: null,\n navigationInstalled: false,\n };\n }\n return g[ERROR_CAPTURE_STATE_KEY]!;\n}\n\nfunction nowIso(): string {\n return new Date().toISOString();\n}\n\nfunction truncate(value: string, max: number): string {\n return value.length > max ? value.slice(0, max) : value;\n}\n\nfunction currentUrl(): string | undefined {\n try {\n return scrubUrl(window.location.href);\n } catch {\n return undefined;\n }\n}\n\n/** Normalize any thrown value into a stable `{ type, message, stack }`. */\nexport function normalizeCapturedError(error: unknown): {\n type: string;\n message: string;\n stack?: string;\n} {\n if (error instanceof Error) {\n return {\n type: error.name || \"Error\",\n message: error.message || String(error),\n stack: typeof error.stack === \"string\" ? error.stack : undefined,\n };\n }\n if (typeof error === \"string\") {\n return { type: \"Error\", message: error };\n }\n if (error && typeof error === \"object\") {\n const record = error as Record<string, unknown>;\n const name = typeof record.name === \"string\" ? record.name : undefined;\n const message =\n typeof record.message === \"string\" ? record.message : undefined;\n const stack = typeof record.stack === \"string\" ? record.stack : undefined;\n if (name || message || stack) {\n return {\n type: name || \"Error\",\n message: message || safeStringify(error),\n stack,\n };\n }\n return { type: \"Error\", message: safeStringify(error) };\n }\n return { type: \"Error\", message: String(error) };\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value) ?? String(value);\n } catch {\n return String(value);\n }\n}\n\nfunction coerceTags(\n tags: CaptureExceptionContext[\"tags\"],\n): Record<string, string> | undefined {\n if (!tags) return undefined;\n const out: Record<string, string> = {};\n let count = 0;\n for (const [key, value] of Object.entries(tags)) {\n if (count >= MAX_TAGS) break;\n if (value === undefined || value === null) continue;\n out[key] = truncate(redactSecrets(String(value)), 200);\n count += 1;\n }\n return Object.keys(out).length ? out : undefined;\n}\n\nfunction coerceExtra(\n extra: CaptureExceptionContext[\"extra\"],\n): Record<string, unknown> | undefined {\n if (!extra || typeof extra !== \"object\") return undefined;\n const out: Record<string, unknown> = {};\n let count = 0;\n for (const [key, value] of Object.entries(extra)) {\n if (count >= MAX_EXTRA_KEYS) break;\n const safeKey = truncate(redactSecrets(key), 100);\n out[safeKey] = SECRET_KEY_RE.test(safeKey)\n ? \"<redacted>\"\n : coerceExtraValue(value, MAX_EXTRA_DEPTH);\n count += 1;\n }\n return Object.keys(out).length ? out : undefined;\n}\n\nfunction coerceExtraValue(value: unknown, depth: number): unknown {\n if (\n value == null ||\n typeof value === \"boolean\" ||\n typeof value === \"number\"\n ) {\n return value;\n }\n if (typeof value === \"string\") {\n return truncate(redactSecrets(value), MAX_EXTRA_STRING_LENGTH);\n }\n if (typeof value === \"bigint\") {\n return truncate(redactSecrets(value.toString()), MAX_EXTRA_STRING_LENGTH);\n }\n if (depth <= 0) {\n return truncate(\n redactSecrets(safeStringify(value)),\n MAX_EXTRA_STRING_LENGTH,\n );\n }\n if (Array.isArray(value)) {\n return value\n .slice(0, MAX_EXTRA_ARRAY_ITEMS)\n .map((item) => coerceExtraValue(item, depth - 1));\n }\n if (typeof value === \"object\") {\n const out: Record<string, unknown> = {};\n let count = 0;\n for (const [rawKey, child] of Object.entries(value)) {\n if (count >= MAX_EXTRA_OBJECT_KEYS) break;\n const key = truncate(redactSecrets(rawKey), 100);\n out[key] = SECRET_KEY_RE.test(key)\n ? \"<redacted>\"\n : coerceExtraValue(child, depth - 1);\n count += 1;\n }\n return out;\n }\n return truncate(redactSecrets(String(value)), MAX_EXTRA_STRING_LENGTH);\n}\n\nfunction firstStackLine(stack: string | undefined): string {\n if (!stack) return \"\";\n const lines = stack.split(\"\\n\").map((line) => line.trim());\n return (\n lines.find((line) => line.startsWith(\"at \") || /:\\d+:\\d+/.test(line)) ??\n lines[1] ??\n \"\"\n );\n}\n\n/** Cheap client-side signature used only for local dedupe. */\nfunction signatureOf(type: string, message: string, stack?: string): string {\n return `${type}|${message}|${firstStackLine(stack)}`;\n}\n\nfunction shouldDedupe(\n runtime: ErrorCaptureRuntime,\n signature: string,\n): boolean {\n const now = Date.now();\n const windowMs = runtime.config.dedupeWindowMs;\n // Opportunistic cleanup so the map can't grow without bound.\n if (runtime.recentSignatures.size > 200) {\n for (const [key, ts] of runtime.recentSignatures) {\n if (now - ts > windowMs) runtime.recentSignatures.delete(key);\n }\n }\n const last = runtime.recentSignatures.get(signature);\n runtime.recentSignatures.set(signature, now);\n return last !== undefined && now - last < windowMs;\n}\n\n/** Append a privacy-safe breadcrumb to the bounded ring buffer. */\nexport function addErrorBreadcrumb(breadcrumb: {\n category: string;\n message: string;\n level?: ExceptionLevel;\n}): void {\n try {\n const runtime = getRuntime();\n runtime.breadcrumbs.push({\n timestamp: nowIso(),\n category: truncate(breadcrumb.category, 60),\n message: truncate(redactSecrets(breadcrumb.message), 300),\n ...(breadcrumb.level ? { level: breadcrumb.level } : {}),\n });\n const max = runtime.config.maxBreadcrumbs;\n if (runtime.breadcrumbs.length > max) {\n runtime.breadcrumbs.splice(0, runtime.breadcrumbs.length - max);\n }\n } catch {\n // breadcrumbs are best-effort\n }\n}\n\nfunction snapshotBreadcrumbs(\n runtime: ErrorCaptureRuntime,\n): ExceptionBreadcrumb[] {\n return runtime.breadcrumbs.slice(-runtime.config.maxBreadcrumbs);\n}\n\nfunction installNavigationBreadcrumbs(runtime: ErrorCaptureRuntime): void {\n if (runtime.navigationInstalled || typeof window === \"undefined\") return;\n runtime.navigationInstalled = true;\n const record = (navType: string) => {\n try {\n addErrorBreadcrumb({\n category: \"navigation\",\n message: `${navType} ${scrubUrl(window.location.href) ?? window.location.pathname}`,\n });\n } catch {\n // ignore\n }\n };\n try {\n const originalPush = window.history.pushState;\n const originalReplace = window.history.replaceState;\n window.history.pushState = function pushState(...args) {\n const result = originalPush.apply(this, args);\n record(\"navigate\");\n return result;\n };\n window.history.replaceState = function replaceState(...args) {\n const result = originalReplace.apply(this, args);\n record(\"replace\");\n return result;\n };\n window.addEventListener(\"popstate\", () => record(\"popstate\"));\n // Seed the trail with the initial location.\n record(\"load\");\n } catch {\n // navigation breadcrumbs are best-effort\n }\n}\n\nfunction buildEvent(\n runtime: ErrorCaptureRuntime,\n normalized: { type: string; message: string; stack?: string },\n options: {\n handled: boolean;\n level: ExceptionLevel;\n tags?: Record<string, string>;\n extra?: Record<string, unknown>;\n },\n): CapturedExceptionEvent {\n const context = runtime.config.getSessionContext?.() ?? {};\n const stack = normalized.stack\n ? truncate(redactSecrets(normalized.stack), MAX_STACK_LENGTH)\n : undefined;\n return {\n type: truncate(normalized.type || \"Error\", 200),\n message: truncate(\n redactSecrets(normalized.message || \"\"),\n MAX_MESSAGE_LENGTH,\n ),\n ...(stack ? { stack } : {}),\n handled: options.handled,\n level: options.level,\n occurredAt: nowIso(),\n ...(currentUrl() ? { url: currentUrl() } : {}),\n ...(runtime.config.release ? { release: runtime.config.release } : {}),\n ...(runtime.config.environment\n ? { environment: runtime.config.environment }\n : {}),\n ...(context.sessionId ? { sessionId: context.sessionId } : {}),\n ...(context.replayId ? { sessionReplayId: context.replayId } : {}),\n ...(context.anonymousId ? { anonymousId: context.anonymousId } : {}),\n breadcrumbs: snapshotBreadcrumbs(runtime),\n ...(options.tags ? { tags: options.tags } : {}),\n ...(options.extra ? { extra: options.extra } : {}),\n };\n}\n\nfunction dispatch(\n runtime: ErrorCaptureRuntime,\n event: CapturedExceptionEvent,\n emitToReplay: boolean,\n): void {\n const signature = signatureOf(event.type, event.message, event.stack);\n if (shouldDedupe(runtime, signature)) return;\n try {\n runtime.config.send(event);\n } catch {\n // transport must never throw into the host app\n }\n if (emitToReplay) {\n try {\n runtime.config.emitReplayEvent?.(event);\n } catch {\n // replay timeline emission is best-effort\n }\n }\n // Record the exception itself as a breadcrumb so a following error carries\n // the prior failure in its trail.\n addErrorBreadcrumb({\n category: \"exception\",\n message: `${event.type}: ${event.message}`,\n level: event.level,\n });\n}\n\n/**\n * Capture a handled exception. Mirrors Sentry's `captureException(err, ctx)`.\n * Safe to call before `configureTracking` has run — it simply no-ops if no\n * transport is installed yet.\n */\nexport function captureException(\n error: unknown,\n context: CaptureExceptionContext = {},\n): void {\n try {\n const runtime = getRuntime();\n const normalized = normalizeCapturedError(error);\n const event = buildEvent(runtime, normalized, {\n handled: true,\n level: context.level ?? \"error\",\n tags: coerceTags(context.tags),\n extra: coerceExtra(context.extra),\n });\n dispatch(runtime, event, true);\n } catch {\n // never throw from capture\n }\n}\n\n/**\n * Capture a message string as an exception-like event. Mirrors Sentry's\n * `captureMessage(message, level?)`.\n */\nexport function captureMessage(\n message: string,\n level: ExceptionLevel = \"info\",\n): void {\n try {\n const runtime = getRuntime();\n const event = buildEvent(\n runtime,\n { type: \"Message\", message: String(message ?? \"\") },\n { handled: true, level },\n );\n dispatch(runtime, event, true);\n } catch {\n // never throw from capture\n }\n}\n\n/**\n * Install auto-capture + wire the transport. Idempotent: re-invoking updates\n * the config (and (re)installs global handlers) without duplicating listeners.\n * Returns a disposer that removes the global handlers.\n */\nexport function installErrorCapture(\n options: InstallErrorCaptureOptions,\n): () => void {\n const runtime = getRuntime();\n runtime.config = {\n ...runtime.config,\n ...options,\n captureGlobalErrors: options.captureGlobalErrors ?? true,\n captureUnhandledRejections: options.captureUnhandledRejections ?? true,\n maxBreadcrumbs: options.maxBreadcrumbs ?? runtime.config.maxBreadcrumbs,\n dedupeWindowMs: options.dedupeWindowMs ?? runtime.config.dedupeWindowMs,\n };\n\n if (typeof window === \"undefined\") return () => {};\n\n installNavigationBreadcrumbs(runtime);\n\n // Tear down any previously-installed handlers before reinstalling so a second\n // configureTracking call doesn't double-report.\n runtime.removeHandlers?.();\n runtime.removeHandlers = null;\n\n const removers: Array<() => void> = [];\n\n if (runtime.config.captureGlobalErrors) {\n const onError = (event: ErrorEvent) => {\n try {\n const error = event?.error;\n const normalized = error\n ? normalizeCapturedError(error)\n : {\n type: \"Error\",\n message: String(event?.message ?? \"Uncaught error\"),\n };\n // Global errors are already logged by the session replay recorder, so\n // don't re-emit them onto the replay timeline (avoid double-counting).\n dispatch(\n runtime,\n buildEvent(runtime, normalized, {\n handled: false,\n level: \"error\",\n }),\n false,\n );\n } catch {\n // never throw from the listener\n }\n };\n window.addEventListener(\"error\", onError as EventListener);\n removers.push(() =>\n window.removeEventListener(\"error\", onError as EventListener),\n );\n }\n\n if (runtime.config.captureUnhandledRejections) {\n const onRejection = (event: PromiseRejectionEvent) => {\n try {\n const reason = event?.reason;\n const normalized = normalizeCapturedError(reason);\n if (!normalized.type || normalized.type === \"Error\") {\n normalized.type = \"UnhandledRejection\";\n }\n dispatch(\n runtime,\n buildEvent(runtime, normalized, {\n handled: false,\n level: \"error\",\n }),\n false,\n );\n } catch {\n // never throw from the listener\n }\n };\n window.addEventListener(\"unhandledrejection\", onRejection as EventListener);\n removers.push(() =>\n window.removeEventListener(\n \"unhandledrejection\",\n onRejection as EventListener,\n ),\n );\n }\n\n runtime.installed = true;\n runtime.removeHandlers = () => {\n for (const remove of removers) {\n try {\n remove();\n } catch {\n // best-effort teardown\n }\n }\n runtime.removeHandlers = null;\n runtime.installed = false;\n };\n return runtime.removeHandlers;\n}\n\nexport function isErrorCaptureInstalled(): boolean {\n return getRuntime().installed;\n}\n"]}
1
+ {"version":3,"file":"error-capture.js","sourceRoot":"","sources":["../../src/client/error-capture.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * First-party, Sentry-style browser error capture for the Agent Native\n * analytics SDK.\n *\n * Two responsibilities:\n * 1. Automatic capture of uncaught exceptions (`window.onerror`) and\n * unhandled promise rejections (`unhandledrejection`).\n * 2. A documented manual API — `captureException(error, context?)` and\n * `captureMessage(message, level?)` — mirroring Sentry's ergonomics.\n *\n * Captured exceptions are handed to a `send` callback (wired by\n * `configureTracking` to the first-party analytics `/track` ingest as a\n * dedicated `$exception` event) and are tagged with the current analytics\n * session id + session replay id so each error links back to the recording it\n * happened in. Everything here is defensive: capture must never throw back into\n * the host app, so every path is wrapped and failures are swallowed.\n *\n * Stack parsing and fingerprinting are intentionally done authoritatively on\n * the server (see the analytics template's `server/lib/error-capture.ts`); the\n * client sends a compact, bounded payload (type/message/raw stack/context) and\n * the server normalizes + groups it. That keeps one tested source of truth for\n * grouping instead of duplicating parser logic across the wire.\n */\nimport { scrubUrl } from \"./url-scrub.js\";\n\nexport type ExceptionLevel = \"fatal\" | \"error\" | \"warning\" | \"info\" | \"debug\";\n\n/** Extra Sentry-style context accepted by `captureException`. */\nexport interface CaptureExceptionContext {\n /** Low-cardinality searchable tags. Values are coerced to strings. */\n tags?: Record<string, string | number | boolean | null | undefined>;\n /** Structured, higher-cardinality detail shown on the event. */\n extra?: Record<string, unknown>;\n /** Severity; defaults to \"error\". */\n level?: ExceptionLevel;\n}\n\nexport interface ExceptionBreadcrumb {\n timestamp: string;\n category: string;\n message: string;\n level?: ExceptionLevel;\n}\n\n/**\n * Compact exception payload emitted to transport. Field names are the wire\n * contract the analytics server ingest reads — keep them stable.\n */\nexport interface CapturedExceptionEvent {\n /** Error class/name, e.g. \"TypeError\". \"Message\" for `captureMessage`. */\n type: string;\n message: string;\n /** Raw (bounded, redacted) stack string; server parses it into frames. */\n stack?: string;\n /** False for uncaught/global errors, true for manually handled ones. */\n handled: boolean;\n level: ExceptionLevel;\n /** ISO timestamp of the occurrence. */\n occurredAt: string;\n url?: string;\n release?: string;\n environment?: string;\n sessionId?: string;\n /** Client session replay id (localStorage) for replay linkage. */\n sessionReplayId?: string;\n anonymousId?: string;\n breadcrumbs: ExceptionBreadcrumb[];\n tags?: Record<string, string>;\n extra?: Record<string, unknown>;\n}\n\nexport interface InstallErrorCaptureOptions {\n /** Transport for a captured exception. Must not throw. */\n send: (event: CapturedExceptionEvent) => void;\n /** Resolve current analytics/session-replay identifiers at capture time. */\n getSessionContext?: () => {\n sessionId?: string;\n anonymousId?: string;\n replayId?: string;\n };\n /**\n * Optional hook to also surface a manual capture on the session replay\n * timeline. Only invoked for manual `captureException`/`captureMessage`;\n * auto-captured global errors are already recorded by the replay recorder.\n */\n emitReplayEvent?: (event: CapturedExceptionEvent) => void;\n release?: string;\n environment?: string;\n /** Auto-capture `window.onerror`. Defaults to true. */\n captureGlobalErrors?: boolean;\n /** Auto-capture `unhandledrejection`. Defaults to true. */\n captureUnhandledRejections?: boolean;\n /** Breadcrumb ring buffer size. Defaults to 20. */\n maxBreadcrumbs?: number;\n /** Dedupe window (ms) for identical signatures. Defaults to 3000. */\n dedupeWindowMs?: number;\n}\n\ninterface ErrorCaptureRuntime {\n installed: boolean;\n config: Required<\n Pick<\n InstallErrorCaptureOptions,\n | \"captureGlobalErrors\"\n | \"captureUnhandledRejections\"\n | \"maxBreadcrumbs\"\n | \"dedupeWindowMs\"\n >\n > &\n Omit<\n InstallErrorCaptureOptions,\n | \"captureGlobalErrors\"\n | \"captureUnhandledRejections\"\n | \"maxBreadcrumbs\"\n | \"dedupeWindowMs\"\n >;\n breadcrumbs: ExceptionBreadcrumb[];\n recentSignatures: Map<string, number>;\n removeHandlers: (() => void) | null;\n navigationInstalled: boolean;\n}\n\nconst MAX_MESSAGE_LENGTH = 1000;\nconst MAX_STACK_LENGTH = 8000;\nconst MAX_TAGS = 30;\nconst MAX_EXTRA_KEYS = 50;\nconst MAX_EXTRA_DEPTH = 4;\nconst MAX_EXTRA_OBJECT_KEYS = 20;\nconst MAX_EXTRA_ARRAY_ITEMS = 20;\nconst MAX_EXTRA_STRING_LENGTH = 2000;\n\nconst ERROR_CAPTURE_STATE_KEY = Symbol.for(\"agent-native.client.errorCapture\");\n\n// Reuse the same credential-looking redaction the replay capture uses so a\n// stack/message that echoes a token never leaves the browser in the clear.\nconst SECRET_KEY_FRAGMENT =\n \"(?:authorization|cookie|set[-_]?cookie|token|secret|password|passwd|pwd|api[-_]?key|apikey|session|credential)\";\nconst BEARER_RE = /\\b(bearer|basic)\\s+[a-z0-9._~+/-]+=*/gi;\nconst UNQUOTED_SECRET_RE = new RegExp(\n `([\"']?)([A-Za-z0-9_$.-]*${SECRET_KEY_FRAGMENT}[A-Za-z0-9_$.-]*)\\\\1(\\\\s*[:=]\\\\s*)([^\"',\\\\s;}\\\\]]+)`,\n \"gi\",\n);\nconst SECRET_KEY_RE = new RegExp(SECRET_KEY_FRAGMENT, \"i\");\n\nfunction redactSecrets(value: string): string {\n return value\n .replace(BEARER_RE, \"$1 <redacted>\")\n .replace(UNQUOTED_SECRET_RE, \"$1$2$1$3<redacted>\");\n}\n\nfunction getRuntime(): ErrorCaptureRuntime {\n const g = globalThis as typeof globalThis & {\n [ERROR_CAPTURE_STATE_KEY]?: ErrorCaptureRuntime;\n };\n if (!g[ERROR_CAPTURE_STATE_KEY]) {\n g[ERROR_CAPTURE_STATE_KEY] = {\n installed: false,\n config: {\n send: () => {},\n captureGlobalErrors: true,\n captureUnhandledRejections: true,\n maxBreadcrumbs: 20,\n dedupeWindowMs: 3000,\n },\n breadcrumbs: [],\n recentSignatures: new Map(),\n removeHandlers: null,\n navigationInstalled: false,\n };\n }\n return g[ERROR_CAPTURE_STATE_KEY]!;\n}\n\nfunction nowIso(): string {\n return new Date().toISOString();\n}\n\nfunction truncate(value: string, max: number): string {\n return value.length > max ? value.slice(0, max) : value;\n}\n\nfunction currentUrl(): string | undefined {\n try {\n return scrubUrl(window.location.href);\n } catch {\n return undefined;\n }\n}\n\n/** Normalize any thrown value into a stable `{ type, message, stack }`. */\nexport function normalizeCapturedError(error: unknown): {\n type: string;\n message: string;\n stack?: string;\n} {\n if (error instanceof Error) {\n return {\n type: error.name || \"Error\",\n message: error.message || String(error),\n stack: typeof error.stack === \"string\" ? error.stack : undefined,\n };\n }\n if (typeof error === \"string\") {\n return { type: \"Error\", message: error };\n }\n if (error && typeof error === \"object\") {\n const record = error as Record<string, unknown>;\n const name = typeof record.name === \"string\" ? record.name : undefined;\n const message =\n typeof record.message === \"string\" ? record.message : undefined;\n const stack = typeof record.stack === \"string\" ? record.stack : undefined;\n if (name || message || stack) {\n return {\n type: name || \"Error\",\n message: message || safeStringify(error),\n stack,\n };\n }\n return { type: \"Error\", message: safeStringify(error) };\n }\n return { type: \"Error\", message: String(error) };\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value) ?? String(value);\n } catch {\n return String(value);\n }\n}\n\nfunction coerceTags(\n tags: CaptureExceptionContext[\"tags\"],\n): Record<string, string> | undefined {\n if (!tags) return undefined;\n const out: Record<string, string> = {};\n let count = 0;\n for (const [key, value] of Object.entries(tags)) {\n if (count >= MAX_TAGS) break;\n if (value === undefined || value === null) continue;\n out[key] = truncate(redactSecrets(String(value)), 200);\n count += 1;\n }\n return Object.keys(out).length ? out : undefined;\n}\n\nfunction coerceExtra(\n extra: CaptureExceptionContext[\"extra\"],\n): Record<string, unknown> | undefined {\n if (!extra || typeof extra !== \"object\") return undefined;\n const out: Record<string, unknown> = {};\n let count = 0;\n for (const [key, value] of Object.entries(extra)) {\n if (count >= MAX_EXTRA_KEYS) break;\n const safeKey = truncate(redactSecrets(key), 100);\n out[safeKey] = SECRET_KEY_RE.test(safeKey)\n ? \"<redacted>\"\n : coerceExtraValue(value, MAX_EXTRA_DEPTH);\n count += 1;\n }\n return Object.keys(out).length ? out : undefined;\n}\n\nfunction coerceExtraValue(value: unknown, depth: number): unknown {\n if (\n value == null ||\n typeof value === \"boolean\" ||\n typeof value === \"number\"\n ) {\n return value;\n }\n if (typeof value === \"string\") {\n return truncate(redactSecrets(value), MAX_EXTRA_STRING_LENGTH);\n }\n if (typeof value === \"bigint\") {\n return truncate(redactSecrets(value.toString()), MAX_EXTRA_STRING_LENGTH);\n }\n if (depth <= 0) {\n return truncate(\n redactSecrets(safeStringify(value)),\n MAX_EXTRA_STRING_LENGTH,\n );\n }\n if (Array.isArray(value)) {\n return value\n .slice(0, MAX_EXTRA_ARRAY_ITEMS)\n .map((item) => coerceExtraValue(item, depth - 1));\n }\n if (typeof value === \"object\") {\n const out: Record<string, unknown> = {};\n let count = 0;\n for (const [rawKey, child] of Object.entries(value)) {\n if (count >= MAX_EXTRA_OBJECT_KEYS) break;\n const key = truncate(redactSecrets(rawKey), 100);\n out[key] = SECRET_KEY_RE.test(key)\n ? \"<redacted>\"\n : coerceExtraValue(child, depth - 1);\n count += 1;\n }\n return out;\n }\n return truncate(redactSecrets(String(value)), MAX_EXTRA_STRING_LENGTH);\n}\n\nfunction firstStackLine(stack: string | undefined): string {\n if (!stack) return \"\";\n const lines = stack.split(\"\\n\").map((line) => line.trim());\n return (\n lines.find((line) => line.startsWith(\"at \") || /:\\d+:\\d+/.test(line)) ??\n lines[1] ??\n \"\"\n );\n}\n\n/** Cheap client-side signature used only for local dedupe. */\nfunction signatureOf(type: string, message: string, stack?: string): string {\n return `${type}|${message}|${firstStackLine(stack)}`;\n}\n\nfunction normalizeGlobalErrorEvent(event: ErrorEvent): {\n type: string;\n message: string;\n stack?: string;\n} {\n const error = event?.error;\n const normalized = error\n ? normalizeCapturedError(error)\n : {\n type: \"Error\",\n message: String(event?.message ?? \"Uncaught error\"),\n };\n\n if (!normalized.stack && event?.filename) {\n const line = event.lineno ?? 0;\n const col = event.colno ?? 0;\n normalized.stack = `at ${event.filename}:${line}:${col}`;\n }\n\n return normalized;\n}\n\nfunction shouldIgnoreAutoCapturedError(normalized: {\n type: string;\n message: string;\n stack?: string;\n}): boolean {\n const message = (normalized.message || \"\").trim();\n const stack = normalized.stack || \"\";\n\n if (\n /^ResizeObserver loop (?:limit exceeded|completed with undelivered notifications\\.?)$/i.test(\n message,\n )\n ) {\n return true;\n }\n\n if (\n normalized.type === \"InvalidStateError\" &&\n /^Transition was aborted because of invalid state$/i.test(message)\n ) {\n return true;\n }\n\n if (\n /^This script should only be loaded in a browser extension\\.?$/i.test(\n message,\n )\n ) {\n return true;\n }\n\n const hasExtensionFrame =\n /\\b(?:chrome|moz|safari|webkit)-extension:\\/\\//i.test(stack) ||\n /\\binjectScriptAdjust\\.js\\b/i.test(stack);\n if (\n hasExtensionFrame &&\n /^(?:TypeError:\\s*)?Failed to fetch$/i.test(message)\n ) {\n return true;\n }\n\n return false;\n}\n\nfunction shouldDedupe(\n runtime: ErrorCaptureRuntime,\n signature: string,\n): boolean {\n const now = Date.now();\n const windowMs = runtime.config.dedupeWindowMs;\n // Opportunistic cleanup so the map can't grow without bound.\n if (runtime.recentSignatures.size > 200) {\n for (const [key, ts] of runtime.recentSignatures) {\n if (now - ts > windowMs) runtime.recentSignatures.delete(key);\n }\n }\n const last = runtime.recentSignatures.get(signature);\n runtime.recentSignatures.set(signature, now);\n return last !== undefined && now - last < windowMs;\n}\n\n/** Append a privacy-safe breadcrumb to the bounded ring buffer. */\nexport function addErrorBreadcrumb(breadcrumb: {\n category: string;\n message: string;\n level?: ExceptionLevel;\n}): void {\n try {\n const runtime = getRuntime();\n runtime.breadcrumbs.push({\n timestamp: nowIso(),\n category: truncate(breadcrumb.category, 60),\n message: truncate(redactSecrets(breadcrumb.message), 300),\n ...(breadcrumb.level ? { level: breadcrumb.level } : {}),\n });\n const max = runtime.config.maxBreadcrumbs;\n if (runtime.breadcrumbs.length > max) {\n runtime.breadcrumbs.splice(0, runtime.breadcrumbs.length - max);\n }\n } catch {\n // breadcrumbs are best-effort\n }\n}\n\nfunction snapshotBreadcrumbs(\n runtime: ErrorCaptureRuntime,\n): ExceptionBreadcrumb[] {\n return runtime.breadcrumbs.slice(-runtime.config.maxBreadcrumbs);\n}\n\nfunction installNavigationBreadcrumbs(runtime: ErrorCaptureRuntime): void {\n if (runtime.navigationInstalled || typeof window === \"undefined\") return;\n runtime.navigationInstalled = true;\n const record = (navType: string) => {\n try {\n addErrorBreadcrumb({\n category: \"navigation\",\n message: `${navType} ${scrubUrl(window.location.href) ?? window.location.pathname}`,\n });\n } catch {\n // ignore\n }\n };\n try {\n const originalPush = window.history.pushState;\n const originalReplace = window.history.replaceState;\n window.history.pushState = function pushState(...args) {\n const result = originalPush.apply(this, args);\n record(\"navigate\");\n return result;\n };\n window.history.replaceState = function replaceState(...args) {\n const result = originalReplace.apply(this, args);\n record(\"replace\");\n return result;\n };\n window.addEventListener(\"popstate\", () => record(\"popstate\"));\n // Seed the trail with the initial location.\n record(\"load\");\n } catch {\n // navigation breadcrumbs are best-effort\n }\n}\n\nfunction buildEvent(\n runtime: ErrorCaptureRuntime,\n normalized: { type: string; message: string; stack?: string },\n options: {\n handled: boolean;\n level: ExceptionLevel;\n tags?: Record<string, string>;\n extra?: Record<string, unknown>;\n },\n): CapturedExceptionEvent {\n const context = runtime.config.getSessionContext?.() ?? {};\n const stack = normalized.stack\n ? truncate(redactSecrets(normalized.stack), MAX_STACK_LENGTH)\n : undefined;\n return {\n type: truncate(normalized.type || \"Error\", 200),\n message: truncate(\n redactSecrets(normalized.message || \"\"),\n MAX_MESSAGE_LENGTH,\n ),\n ...(stack ? { stack } : {}),\n handled: options.handled,\n level: options.level,\n occurredAt: nowIso(),\n ...(currentUrl() ? { url: currentUrl() } : {}),\n ...(runtime.config.release ? { release: runtime.config.release } : {}),\n ...(runtime.config.environment\n ? { environment: runtime.config.environment }\n : {}),\n ...(context.sessionId ? { sessionId: context.sessionId } : {}),\n ...(context.replayId ? { sessionReplayId: context.replayId } : {}),\n ...(context.anonymousId ? { anonymousId: context.anonymousId } : {}),\n breadcrumbs: snapshotBreadcrumbs(runtime),\n ...(options.tags ? { tags: options.tags } : {}),\n ...(options.extra ? { extra: options.extra } : {}),\n };\n}\n\nfunction dispatch(\n runtime: ErrorCaptureRuntime,\n event: CapturedExceptionEvent,\n emitToReplay: boolean,\n): void {\n const signature = signatureOf(event.type, event.message, event.stack);\n if (shouldDedupe(runtime, signature)) return;\n try {\n runtime.config.send(event);\n } catch {\n // transport must never throw into the host app\n }\n if (emitToReplay) {\n try {\n runtime.config.emitReplayEvent?.(event);\n } catch {\n // replay timeline emission is best-effort\n }\n }\n // Record the exception itself as a breadcrumb so a following error carries\n // the prior failure in its trail.\n addErrorBreadcrumb({\n category: \"exception\",\n message: `${event.type}: ${event.message}`,\n level: event.level,\n });\n}\n\n/**\n * Capture a handled exception. Mirrors Sentry's `captureException(err, ctx)`.\n * Safe to call before `configureTracking` has run — it simply no-ops if no\n * transport is installed yet.\n */\nexport function captureException(\n error: unknown,\n context: CaptureExceptionContext = {},\n): void {\n try {\n const runtime = getRuntime();\n const normalized = normalizeCapturedError(error);\n const event = buildEvent(runtime, normalized, {\n handled: true,\n level: context.level ?? \"error\",\n tags: coerceTags(context.tags),\n extra: coerceExtra(context.extra),\n });\n dispatch(runtime, event, true);\n } catch {\n // never throw from capture\n }\n}\n\n/**\n * Capture a message string as an exception-like event. Mirrors Sentry's\n * `captureMessage(message, level?)`.\n */\nexport function captureMessage(\n message: string,\n level: ExceptionLevel = \"info\",\n): void {\n try {\n const runtime = getRuntime();\n const event = buildEvent(\n runtime,\n { type: \"Message\", message: String(message ?? \"\") },\n { handled: true, level },\n );\n dispatch(runtime, event, true);\n } catch {\n // never throw from capture\n }\n}\n\n/**\n * Install auto-capture + wire the transport. Idempotent: re-invoking updates\n * the config (and (re)installs global handlers) without duplicating listeners.\n * Returns a disposer that removes the global handlers.\n */\nexport function installErrorCapture(\n options: InstallErrorCaptureOptions,\n): () => void {\n const runtime = getRuntime();\n runtime.config = {\n ...runtime.config,\n ...options,\n captureGlobalErrors: options.captureGlobalErrors ?? true,\n captureUnhandledRejections: options.captureUnhandledRejections ?? true,\n maxBreadcrumbs: options.maxBreadcrumbs ?? runtime.config.maxBreadcrumbs,\n dedupeWindowMs: options.dedupeWindowMs ?? runtime.config.dedupeWindowMs,\n };\n\n if (typeof window === \"undefined\") return () => {};\n\n installNavigationBreadcrumbs(runtime);\n\n // Tear down any previously-installed handlers before reinstalling so a second\n // configureTracking call doesn't double-report.\n runtime.removeHandlers?.();\n runtime.removeHandlers = null;\n\n const removers: Array<() => void> = [];\n\n if (runtime.config.captureGlobalErrors) {\n const onError = (event: ErrorEvent) => {\n try {\n const normalized = normalizeGlobalErrorEvent(event);\n if (shouldIgnoreAutoCapturedError(normalized)) return;\n // Global errors are already logged by the session replay recorder, so\n // don't re-emit them onto the replay timeline (avoid double-counting).\n dispatch(\n runtime,\n buildEvent(runtime, normalized, {\n handled: false,\n level: \"error\",\n }),\n false,\n );\n } catch {\n // never throw from the listener\n }\n };\n window.addEventListener(\"error\", onError as EventListener);\n removers.push(() =>\n window.removeEventListener(\"error\", onError as EventListener),\n );\n }\n\n if (runtime.config.captureUnhandledRejections) {\n const onRejection = (event: PromiseRejectionEvent) => {\n try {\n const reason = event?.reason;\n const normalized = normalizeCapturedError(reason);\n if (!normalized.type || normalized.type === \"Error\") {\n normalized.type = \"UnhandledRejection\";\n }\n if (shouldIgnoreAutoCapturedError(normalized)) return;\n dispatch(\n runtime,\n buildEvent(runtime, normalized, {\n handled: false,\n level: \"error\",\n }),\n false,\n );\n } catch {\n // never throw from the listener\n }\n };\n window.addEventListener(\"unhandledrejection\", onRejection as EventListener);\n removers.push(() =>\n window.removeEventListener(\n \"unhandledrejection\",\n onRejection as EventListener,\n ),\n );\n }\n\n runtime.installed = true;\n runtime.removeHandlers = () => {\n for (const remove of removers) {\n try {\n remove();\n } catch {\n // best-effort teardown\n }\n }\n runtime.removeHandlers = null;\n runtime.installed = false;\n };\n return runtime.removeHandlers;\n}\n\nexport function isErrorCaptureInstalled(): boolean {\n return getRuntime().installed;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"EmbeddedExtension.d.ts","sourceRoot":"","sources":["../../../src/client/extensions/EmbeddedExtension.tsx"],"names":[],"mappings":"AAmFA,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB;2CACuC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf;iDAC6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzC,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;qEAEiE;IACjE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;;4EAGwE;IACxE,aAAa,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,WAAW,EACX,MAAM,EACN,OAAO,EACP,SAAS,EACT,aAAkB,EAClB,OAAO,EACP,aAAa,GACd,EAAE,sBAAsB,sCAkTxB"}
1
+ {"version":3,"file":"EmbeddedExtension.d.ts","sourceRoot":"","sources":["../../../src/client/extensions/EmbeddedExtension.tsx"],"names":[],"mappings":"AAuFA,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB;2CACuC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf;iDAC6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzC,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;qEAEiE;IACjE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;;4EAGwE;IACxE,aAAa,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,WAAW,EACX,MAAM,EACN,OAAO,EACP,SAAS,EACT,aAAkB,EAClB,OAAO,EACP,aAAa,GACd,EAAE,sBAAsB,sCAkTxB"}
@@ -14,6 +14,8 @@ import { useT } from "../i18n.js";
14
14
  import { deleteOrHideExtension, invalidateExtensionRemoval, } from "./delete-extension.js";
15
15
  import { extensionLoadError, extensionLoadErrorStatus, shouldRetryExtensionLoad, } from "./extension-load-error.js";
16
16
  import { isAllowedExtensionPath, sanitizeExtensionRequestOptions, checkBridgePolicy, } from "./iframe-bridge.js";
17
+ import { normalizeAgentNativeExtensionSandbox } from "./portable-extension.js";
18
+ const EXTENSION_IFRAME_SANDBOX = normalizeAgentNativeExtensionSandbox(undefined);
17
19
  // Read the host app's *actual* computed theme values for the shared token set
18
20
  // (THEME_VAR_NAMES). The iframe ships with a generic baked palette
19
21
  // (getThemeVars); syncing the live values keeps embedded extensions visually
@@ -278,7 +280,7 @@ export function EmbeddedExtension({ extensionId, slotId, context, className, ini
278
280
  return null;
279
281
  return (_jsx("div", { className: className, style: { height: initialHeight }, "aria-busy": "true" }));
280
282
  }
281
- return (_jsxs("div", { className: `relative group/embedded-extension ${className ?? ""}`, children: [_jsx("iframe", { ref: iframeRef, src: iframeSrc, title: extension.name, sandbox: "allow-scripts allow-forms", style: { width: "100%", border: 0, height, display: "block" }, onLoad: () => {
283
+ return (_jsxs("div", { className: `relative group/embedded-extension ${className ?? ""}`, children: [_jsx("iframe", { ref: iframeRef, src: iframeSrc, title: extension.name, sandbox: EXTENSION_IFRAME_SANDBOX, style: { width: "100%", border: 0, height, display: "block" }, onLoad: () => {
282
284
  iframeRef.current?.contentWindow?.postMessage({ type: "agent-native-slot-context", context: context ?? {} }, "*");
283
285
  // Re-assert theme once the iframe document is live. The src bakes in
284
286
  // the initial dark state, but this covers the race where isDark
@@ -1 +1 @@
1
- {"version":3,"file":"EmbeddedExtension.js","sourceRoot":"","sources":["../../../src/client/extensions/EmbeddedExtension.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n IconDots,\n IconExternalLink,\n IconLayoutSidebarRightCollapse,\n IconTrash,\n} from \"@tabler/icons-react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { useNavigate } from \"react-router\";\n\nimport { extensionPath } from \"../../extensions/path.js\";\nimport { THEME_VAR_NAMES } from \"../../extensions/theme.js\";\nimport { sendToAgentChat } from \"../agent-chat.js\";\nimport { agentNativePath } from \"../api-path.js\";\nimport { useAppearance } from \"../appearance.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"../components/ui/tooltip.js\";\nimport { useT } from \"../i18n.js\";\nimport {\n deleteOrHideExtension,\n invalidateExtensionRemoval,\n} from \"./delete-extension.js\";\nimport {\n extensionLoadError,\n extensionLoadErrorStatus,\n shouldRetryExtensionLoad,\n} from \"./extension-load-error.js\";\nimport {\n isAllowedExtensionPath,\n sanitizeExtensionRequestOptions,\n checkBridgePolicy,\n type BridgePolicyContext,\n type ExtensionBridgeRole,\n} from \"./iframe-bridge.js\";\n\ninterface Extension {\n id: string;\n name: string;\n description?: string;\n content?: string;\n updatedAt?: string;\n canDelete?: boolean;\n source?: {\n mode?: \"database\" | \"local-files\";\n permissions?: BridgePolicyContext[\"permissions\"];\n };\n}\n\n// Read the host app's *actual* computed theme values for the shared token set\n// (THEME_VAR_NAMES). The iframe ships with a generic baked palette\n// (getThemeVars); syncing the live values keeps embedded extensions visually\n// identical to the surrounding app even when a template overrides the default\n// palette (e.g. analytics uses a neutral-gray dark theme, not near-black).\nfunction readHostThemeVars(): Record<string, string> {\n if (typeof document === \"undefined\") return {};\n const computed = getComputedStyle(document.documentElement);\n const vars: Record<string, string> = {};\n for (const name of THEME_VAR_NAMES) {\n const value = computed.getPropertyValue(name).trim();\n if (value) vars[name] = value;\n }\n return vars;\n}\n\nfunction serializeChatValue(value: unknown): string | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value === \"string\") return value;\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nexport interface EmbeddedExtensionProps {\n extensionId: string;\n /** Slot identifier passed via the iframe URL so the extension runtime knows it's\n * embedded and enables auto-resize. */\n slotId: string;\n /** Object pushed into the extension as `window.slotContext`. Re-posted whenever\n * the host re-renders with a new context. */\n context?: Record<string, unknown> | null;\n /** Optional className applied to the iframe container. */\n className?: string;\n /** Initial iframe height before content reports a real height. */\n initialHeight?: number;\n /** Fires once when the embedded iframe first signals content readiness — its\n * first height report, or iframe load as a fallback. Hosts that gate on\n * content paint (e.g. dashboard report screenshots) use this. */\n onReady?: () => void;\n /** Fires when the extension can't be loaded for this viewer (e.g. 403/404 —\n * the extension isn't shared with them or no longer exists). Hosts can use\n * this to render an explanatory fallback instead of a blank panel. By default\n * the component renders nothing on failure (slot-style silent skip). */\n onUnavailable?: (status?: number) => void;\n}\n\n/**\n * Renders a extension inline as a small auto-sized iframe — for use inside an\n * `<ExtensionSlot>`. Different from `<ExtensionViewer>` (which is full-page with a\n * toolbar): no header, sized to content, receives a `slotContext`.\n */\nexport function EmbeddedExtension({\n extensionId,\n slotId,\n context,\n className,\n initialHeight = 80,\n onReady,\n onUnavailable,\n}: EmbeddedExtensionProps) {\n const iframeRef = useRef<HTMLIFrameElement | null>(null);\n // Latch the readiness signal so onReady fires at most once per iframe\n // instance. Reset when the iframe is recreated (extensionId/updatedAt change).\n const onReadyRef = useRef(onReady);\n onReadyRef.current = onReady;\n const readyFiredRef = useRef(false);\n const fireReady = () => {\n if (readyFiredRef.current) return;\n readyFiredRef.current = true;\n onReadyRef.current?.();\n };\n const [height, setHeight] = useState<number>(initialHeight);\n const [isDark, setIsDark] = useState(\n () =>\n typeof document !== \"undefined\" &&\n document.documentElement.classList.contains(\"dark\"),\n );\n // (audit H4) Mirror ExtensionViewer's role-aware gating; deny-by-default until\n // the iframe's render binding announcement arrives.\n const bridgeContextRef = useRef<BridgePolicyContext>({\n role: \"viewer\",\n isAuthor: false,\n });\n // (audit H4) Latch the render binding once per iframe instance. The shell\n // posts the server-resolved binding BEFORE user content runs; any later\n // agent-native-extension-binding message is attacker-controllable (it\n // originates inside the same sandboxed realm as user code) and must be\n // ignored so a viewer cannot self-escalate to owner.\n const bindingLatchedRef = useRef(false);\n\n useEffect(() => {\n setIsDark(document.documentElement.classList.contains(\"dark\"));\n const observer = new MutationObserver(() => {\n setIsDark(document.documentElement.classList.contains(\"dark\"));\n });\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\"],\n });\n return () => observer.disconnect();\n }, []);\n\n const {\n data: extension,\n isFetching,\n isLoading,\n isError,\n error,\n } = useQuery<Extension>({\n queryKey: [\"extension\", extensionId],\n queryFn: async () => {\n const res = await fetch(\n agentNativePath(`/_agent-native/extensions/${extensionId}`),\n );\n if (res.status === 404) {\n throw extensionLoadError(404, \"Extension not found\");\n }\n if (res.status === 403) {\n throw extensionLoadError(403, \"Extension access denied\");\n }\n if (!res.ok) {\n throw extensionLoadError(res.status, \"Failed to fetch extension\");\n }\n return res.json();\n },\n retry: shouldRetryExtensionLoad,\n retryDelay: (attempt) => Math.min(1000 * 2 ** attempt, 4000),\n });\n\n // Notify the host once when the extension can't be loaded for this viewer so\n // it can show a fallback instead of a blank panel.\n const onUnavailableRef = useRef(onUnavailable);\n onUnavailableRef.current = onUnavailable;\n const unavailableFiredRef = useRef(false);\n useEffect(() => {\n unavailableFiredRef.current = false;\n }, [extensionId]);\n useEffect(() => {\n if (isError && !isFetching && !unavailableFiredRef.current) {\n unavailableFiredRef.current = true;\n onUnavailableRef.current?.(extensionLoadErrorStatus(error));\n }\n }, [isError, isFetching, error]);\n\n // Initial dark state is baked into the URL on first load only; subsequent\n // theme toggles update the iframe's <html class=\"dark\"> via postMessage so\n // the user's interaction state inside the extension survives the toggle.\n const initialDarkRef = useRef(isDark);\n const iframeSrc = useMemo(() => {\n const v = encodeURIComponent(extension?.updatedAt ?? \"\");\n return agentNativePath(\n `/_agent-native/extensions/${extensionId}/render?slot=${encodeURIComponent(slotId)}&dark=${initialDarkRef.current}&v=${v}`,\n );\n }, [extensionId, slotId, extension?.updatedAt]);\n\n // Reset role + binding latch to deny-by-default whenever the iframe is\n // recreated (its key changes). The new render's first binding announcement\n // re-establishes the role.\n useEffect(() => {\n bridgeContextRef.current = { role: \"viewer\", isAuthor: false };\n bindingLatchedRef.current = false;\n readyFiredRef.current = false;\n }, [extensionId, extension?.updatedAt]);\n\n const appearance = useAppearance();\n\n useEffect(() => {\n const win = iframeRef.current?.contentWindow;\n if (!win) return;\n win.postMessage(\n { type: \"agent-native-theme-update\", isDark, vars: readHostThemeVars() },\n \"*\",\n );\n }, [isDark, appearance]);\n\n // Forward slot context whenever it changes. The iframe's own load handler\n // posts the initial value once it's ready; this effect handles updates.\n const contextJson = JSON.stringify(context ?? {});\n useEffect(() => {\n const win = iframeRef.current?.contentWindow;\n if (!win) return;\n win.postMessage(\n { type: \"agent-native-slot-context\", context: context ?? {} },\n \"*\",\n );\n }, [contextJson]);\n\n // Bridge extension requests + height reports.\n useEffect(() => {\n const handleMessage = async (event: MessageEvent) => {\n if (event.source !== iframeRef.current?.contentWindow) return;\n const message = event.data;\n if (!message || typeof message !== \"object\") return;\n\n if (message.type === \"agent-native-extension-binding\") {\n // Only the FIRST announcement (sent by the shell before user content\n // runs) is trusted. Ignore re-announcements — a malicious extension\n // body could otherwise postMessage a forged owner binding to escalate.\n if (bindingLatchedRef.current) return;\n bindingLatchedRef.current = true;\n const binding = (message as any).binding ?? {};\n const role: ExtensionBridgeRole =\n binding.role === \"owner\" ||\n binding.role === \"admin\" ||\n binding.role === \"editor\" ||\n binding.role === \"viewer\"\n ? binding.role\n : \"viewer\";\n bridgeContextRef.current = {\n role,\n isAuthor: !!binding.isAuthor,\n source: binding.source === \"local-files\" ? \"local-files\" : \"database\",\n permissions:\n binding && typeof binding.permissions === \"object\"\n ? binding.permissions\n : undefined,\n };\n return;\n }\n\n if (message.type === \"agent-native-extension-resize\") {\n const h = Number(message.height);\n if (Number.isFinite(h) && h > 0) {\n setHeight(Math.ceil(h));\n // First laid-out height means the content has painted.\n fireReady();\n }\n return;\n }\n\n if (message.type === \"agent-native-send-to-chat\") {\n const text = serializeChatValue((message as any).message);\n if (!text?.trim()) return;\n sendToAgentChat({\n message: text,\n context: serializeChatValue((message as any).context),\n submit: (message as any).submit !== false,\n openSidebar: (message as any).openSidebar !== false,\n });\n return;\n }\n\n if (message.type !== \"agent-native-extension-request\") return;\n\n const requestId = String(message.requestId ?? \"\");\n const path = String(message.path ?? \"\");\n const respond = (payload: Record<string, unknown>) => {\n iframeRef.current?.contentWindow?.postMessage(\n { type: \"agent-native-extension-response\", requestId, ...payload },\n \"*\",\n );\n };\n\n if (!requestId || !isAllowedExtensionPath(path, extensionId)) {\n respond({ error: \"Extension request path is not allowed\" });\n return;\n }\n\n try {\n const options = sanitizeExtensionRequestOptions(message.options);\n // (audit H4) Role-aware gating: viewer-shared extensions can read but not\n // write. The bridge policy is decided here in the parent before the\n // request leaves; the server enforces a second layer.\n const policy = checkBridgePolicy(path, options.method ?? \"GET\", {\n ...bridgeContextRef.current,\n extensionId,\n });\n if (!policy.ok) {\n respond({\n response: {\n ok: false,\n status: 403,\n statusText: \"Forbidden\",\n body: { error: policy.error },\n },\n });\n return;\n }\n // (audit H5) Same extension-bridge tagging as <ExtensionViewer>. action-routes\n // uses these headers to enforce per-action `toolCallable` opt-in.\n const finalHeaders = new Headers(options.headers ?? undefined);\n finalHeaders.set(\"X-Agent-Native-Extension-Bridge\", \"1\");\n finalHeaders.set(\"X-Agent-Native-Extension-Id\", extensionId);\n finalHeaders.set(\"X-Agent-Native-Tool-Bridge\", \"1\");\n finalHeaders.set(\"X-Agent-Native-Tool-Id\", extensionId);\n const res = await fetch(agentNativePath(path), {\n ...options,\n headers: finalHeaders,\n credentials: \"same-origin\",\n });\n const text = await res.text();\n let body: unknown = text;\n if (text) {\n try {\n body = JSON.parse(text);\n } catch {\n body = text;\n }\n }\n respond({\n response: {\n ok: res.ok,\n status: res.status,\n statusText: res.statusText,\n body,\n },\n });\n } catch (err: any) {\n respond({ error: err?.message ?? \"Extension host request failed\" });\n }\n };\n\n window.addEventListener(\"message\", handleMessage);\n return () => window.removeEventListener(\"message\", handleMessage);\n }, [extensionId]);\n\n if (!extension) {\n if (!isLoading && !isFetching) return null;\n return (\n <div\n className={className}\n style={{ height: initialHeight }}\n aria-busy=\"true\"\n />\n );\n }\n\n return (\n <div className={`relative group/embedded-extension ${className ?? \"\"}`}>\n <iframe\n ref={iframeRef}\n key={`${extensionId}-${extension.updatedAt ?? \"\"}`}\n src={iframeSrc}\n title={extension.name}\n sandbox=\"allow-scripts allow-forms\"\n style={{ width: \"100%\", border: 0, height, display: \"block\" }}\n onLoad={() => {\n iframeRef.current?.contentWindow?.postMessage(\n { type: \"agent-native-slot-context\", context: context ?? {} },\n \"*\",\n );\n // Re-assert theme once the iframe document is live. The src bakes in\n // the initial dark state, but this covers the race where isDark\n // settled before the iframe's message listener existed.\n iframeRef.current?.contentWindow?.postMessage(\n {\n type: \"agent-native-theme-update\",\n isDark,\n vars: readHostThemeVars(),\n },\n \"*\",\n );\n // Fallback readiness signal in case the extension never reports a\n // height (e.g. fixed-height content that skips auto-resize).\n fireReady();\n }}\n />\n <EmbeddedToolMenu\n extensionId={extensionId}\n slotId={slotId}\n toolName={extension.name}\n canDelete={extension.canDelete}\n />\n </div>\n );\n}\n\nfunction EmbeddedToolMenu({\n extensionId,\n slotId,\n toolName,\n canDelete,\n}: {\n extensionId: string;\n slotId: string;\n toolName: string;\n canDelete?: boolean;\n}) {\n const t = useT();\n const [open, setOpen] = useState(false);\n const [confirmingDelete, setConfirmingDelete] = useState(false);\n const queryClient = useQueryClient();\n const navigate = useNavigate();\n\n const closeMenu = () => {\n setOpen(false);\n setConfirmingDelete(false);\n };\n\n const removeFromSlot = async () => {\n closeMenu();\n queryClient.setQueryData<any[]>([\"slot-installs\", slotId], (old) =>\n (old ?? []).filter((i) => i.extensionId !== extensionId),\n );\n try {\n await fetch(\n agentNativePath(\n `/_agent-native/slots/${encodeURIComponent(slotId)}/install/${encodeURIComponent(extensionId)}`,\n ),\n { method: \"DELETE\" },\n );\n } finally {\n queryClient.invalidateQueries({ queryKey: [\"slot-installs\", slotId] });\n }\n };\n\n const deleteExtension = async () => {\n closeMenu();\n try {\n await deleteOrHideExtension({ id: extensionId, canDelete });\n invalidateExtensionRemoval(queryClient, extensionId);\n } catch {\n queryClient.invalidateQueries({ queryKey: [\"extension\", extensionId] });\n }\n };\n\n return (\n <Popover\n open={open}\n onOpenChange={(o) => {\n setOpen(o);\n if (!o) setConfirmingDelete(false);\n }}\n >\n <TooltipProvider delayDuration={200}>\n <Tooltip>\n <TooltipTrigger asChild>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"absolute top-1 right-1 flex h-6 w-6 items-center justify-center rounded-md bg-background/60 text-muted-foreground/60 opacity-0 hover:bg-accent hover:text-foreground hover:opacity-100 group-hover/embedded-extension:opacity-100 cursor-pointer transition-opacity\"\n aria-label={t(\"extensions.optionsFor\", { name: toolName })}\n >\n <IconDots className=\"h-3.5 w-3.5\" />\n </button>\n </PopoverTrigger>\n </TooltipTrigger>\n <TooltipContent>\n {t(\"extensions.optionsFor\", { name: toolName })}\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n <PopoverContent align=\"end\" sideOffset={4} className=\"w-56 p-1\">\n {!confirmingDelete ? (\n <div className=\"flex flex-col\">\n <button\n type=\"button\"\n onClick={() => {\n closeMenu();\n navigate(extensionPath(extensionId, toolName));\n }}\n className=\"flex items-center gap-2 rounded-sm px-2 py-1.5 text-[12px] hover:bg-accent cursor-pointer text-left\"\n >\n <IconExternalLink className=\"h-3.5 w-3.5\" />\n <span>{t(\"extensions.openFullView\")}</span>\n </button>\n <button\n type=\"button\"\n onClick={removeFromSlot}\n className=\"flex items-center gap-2 rounded-sm px-2 py-1.5 text-[12px] hover:bg-accent cursor-pointer text-left\"\n >\n <IconLayoutSidebarRightCollapse className=\"h-3.5 w-3.5\" />\n <span>{t(\"extensions.removeFromWidgetArea\")}</span>\n </button>\n {canDelete !== false && (\n <>\n <div className=\"my-1 h-px bg-border/40\" />\n <button\n type=\"button\"\n onClick={() => setConfirmingDelete(true)}\n className=\"flex items-center gap-2 rounded-sm px-2 py-1.5 text-[12px] text-destructive hover:bg-destructive/10 cursor-pointer text-left\"\n >\n <IconTrash className=\"h-3.5 w-3.5\" />\n <span>{t(\"extensions.deleteExtensionEllipsis\")}</span>\n </button>\n </>\n )}\n </div>\n ) : (\n <div className=\"flex flex-col gap-2 p-2\">\n <p className=\"text-[12px]\">\n {t(\"extensions.deleteQuestion\", { name: toolName })}{\" \"}\n {t(\"extensions.deleteEverywhereConfirmation\")}\n </p>\n <div className=\"flex justify-end gap-1\">\n <button\n type=\"button\"\n onClick={() => setConfirmingDelete(false)}\n className=\"rounded-md px-2 py-1 text-[12px] hover:bg-accent cursor-pointer\"\n >\n {t(\"extensions.cancel\")}\n </button>\n <button\n type=\"button\"\n onClick={deleteExtension}\n className=\"rounded-md bg-destructive px-2 py-1 text-[12px] text-destructive-foreground hover:bg-destructive/90 cursor-pointer\"\n >\n {t(\"extensions.delete\")}\n </button>\n </div>\n </div>\n )}\n </PopoverContent>\n </Popover>\n );\n}\n"]}
1
+ {"version":3,"file":"EmbeddedExtension.js","sourceRoot":"","sources":["../../../src/client/extensions/EmbeddedExtension.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n IconDots,\n IconExternalLink,\n IconLayoutSidebarRightCollapse,\n IconTrash,\n} from \"@tabler/icons-react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { useNavigate } from \"react-router\";\n\nimport { extensionPath } from \"../../extensions/path.js\";\nimport { THEME_VAR_NAMES } from \"../../extensions/theme.js\";\nimport { sendToAgentChat } from \"../agent-chat.js\";\nimport { agentNativePath } from \"../api-path.js\";\nimport { useAppearance } from \"../appearance.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"../components/ui/tooltip.js\";\nimport { useT } from \"../i18n.js\";\nimport {\n deleteOrHideExtension,\n invalidateExtensionRemoval,\n} from \"./delete-extension.js\";\nimport {\n extensionLoadError,\n extensionLoadErrorStatus,\n shouldRetryExtensionLoad,\n} from \"./extension-load-error.js\";\nimport {\n isAllowedExtensionPath,\n sanitizeExtensionRequestOptions,\n checkBridgePolicy,\n type BridgePolicyContext,\n type ExtensionBridgeRole,\n} from \"./iframe-bridge.js\";\nimport { normalizeAgentNativeExtensionSandbox } from \"./portable-extension.js\";\n\ninterface Extension {\n id: string;\n name: string;\n description?: string;\n content?: string;\n updatedAt?: string;\n canDelete?: boolean;\n source?: {\n mode?: \"database\" | \"local-files\";\n permissions?: BridgePolicyContext[\"permissions\"];\n };\n}\n\nconst EXTENSION_IFRAME_SANDBOX =\n normalizeAgentNativeExtensionSandbox(undefined);\n\n// Read the host app's *actual* computed theme values for the shared token set\n// (THEME_VAR_NAMES). The iframe ships with a generic baked palette\n// (getThemeVars); syncing the live values keeps embedded extensions visually\n// identical to the surrounding app even when a template overrides the default\n// palette (e.g. analytics uses a neutral-gray dark theme, not near-black).\nfunction readHostThemeVars(): Record<string, string> {\n if (typeof document === \"undefined\") return {};\n const computed = getComputedStyle(document.documentElement);\n const vars: Record<string, string> = {};\n for (const name of THEME_VAR_NAMES) {\n const value = computed.getPropertyValue(name).trim();\n if (value) vars[name] = value;\n }\n return vars;\n}\n\nfunction serializeChatValue(value: unknown): string | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value === \"string\") return value;\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nexport interface EmbeddedExtensionProps {\n extensionId: string;\n /** Slot identifier passed via the iframe URL so the extension runtime knows it's\n * embedded and enables auto-resize. */\n slotId: string;\n /** Object pushed into the extension as `window.slotContext`. Re-posted whenever\n * the host re-renders with a new context. */\n context?: Record<string, unknown> | null;\n /** Optional className applied to the iframe container. */\n className?: string;\n /** Initial iframe height before content reports a real height. */\n initialHeight?: number;\n /** Fires once when the embedded iframe first signals content readiness — its\n * first height report, or iframe load as a fallback. Hosts that gate on\n * content paint (e.g. dashboard report screenshots) use this. */\n onReady?: () => void;\n /** Fires when the extension can't be loaded for this viewer (e.g. 403/404 —\n * the extension isn't shared with them or no longer exists). Hosts can use\n * this to render an explanatory fallback instead of a blank panel. By default\n * the component renders nothing on failure (slot-style silent skip). */\n onUnavailable?: (status?: number) => void;\n}\n\n/**\n * Renders a extension inline as a small auto-sized iframe — for use inside an\n * `<ExtensionSlot>`. Different from `<ExtensionViewer>` (which is full-page with a\n * toolbar): no header, sized to content, receives a `slotContext`.\n */\nexport function EmbeddedExtension({\n extensionId,\n slotId,\n context,\n className,\n initialHeight = 80,\n onReady,\n onUnavailable,\n}: EmbeddedExtensionProps) {\n const iframeRef = useRef<HTMLIFrameElement | null>(null);\n // Latch the readiness signal so onReady fires at most once per iframe\n // instance. Reset when the iframe is recreated (extensionId/updatedAt change).\n const onReadyRef = useRef(onReady);\n onReadyRef.current = onReady;\n const readyFiredRef = useRef(false);\n const fireReady = () => {\n if (readyFiredRef.current) return;\n readyFiredRef.current = true;\n onReadyRef.current?.();\n };\n const [height, setHeight] = useState<number>(initialHeight);\n const [isDark, setIsDark] = useState(\n () =>\n typeof document !== \"undefined\" &&\n document.documentElement.classList.contains(\"dark\"),\n );\n // (audit H4) Mirror ExtensionViewer's role-aware gating; deny-by-default until\n // the iframe's render binding announcement arrives.\n const bridgeContextRef = useRef<BridgePolicyContext>({\n role: \"viewer\",\n isAuthor: false,\n });\n // (audit H4) Latch the render binding once per iframe instance. The shell\n // posts the server-resolved binding BEFORE user content runs; any later\n // agent-native-extension-binding message is attacker-controllable (it\n // originates inside the same sandboxed realm as user code) and must be\n // ignored so a viewer cannot self-escalate to owner.\n const bindingLatchedRef = useRef(false);\n\n useEffect(() => {\n setIsDark(document.documentElement.classList.contains(\"dark\"));\n const observer = new MutationObserver(() => {\n setIsDark(document.documentElement.classList.contains(\"dark\"));\n });\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\"],\n });\n return () => observer.disconnect();\n }, []);\n\n const {\n data: extension,\n isFetching,\n isLoading,\n isError,\n error,\n } = useQuery<Extension>({\n queryKey: [\"extension\", extensionId],\n queryFn: async () => {\n const res = await fetch(\n agentNativePath(`/_agent-native/extensions/${extensionId}`),\n );\n if (res.status === 404) {\n throw extensionLoadError(404, \"Extension not found\");\n }\n if (res.status === 403) {\n throw extensionLoadError(403, \"Extension access denied\");\n }\n if (!res.ok) {\n throw extensionLoadError(res.status, \"Failed to fetch extension\");\n }\n return res.json();\n },\n retry: shouldRetryExtensionLoad,\n retryDelay: (attempt) => Math.min(1000 * 2 ** attempt, 4000),\n });\n\n // Notify the host once when the extension can't be loaded for this viewer so\n // it can show a fallback instead of a blank panel.\n const onUnavailableRef = useRef(onUnavailable);\n onUnavailableRef.current = onUnavailable;\n const unavailableFiredRef = useRef(false);\n useEffect(() => {\n unavailableFiredRef.current = false;\n }, [extensionId]);\n useEffect(() => {\n if (isError && !isFetching && !unavailableFiredRef.current) {\n unavailableFiredRef.current = true;\n onUnavailableRef.current?.(extensionLoadErrorStatus(error));\n }\n }, [isError, isFetching, error]);\n\n // Initial dark state is baked into the URL on first load only; subsequent\n // theme toggles update the iframe's <html class=\"dark\"> via postMessage so\n // the user's interaction state inside the extension survives the toggle.\n const initialDarkRef = useRef(isDark);\n const iframeSrc = useMemo(() => {\n const v = encodeURIComponent(extension?.updatedAt ?? \"\");\n return agentNativePath(\n `/_agent-native/extensions/${extensionId}/render?slot=${encodeURIComponent(slotId)}&dark=${initialDarkRef.current}&v=${v}`,\n );\n }, [extensionId, slotId, extension?.updatedAt]);\n\n // Reset role + binding latch to deny-by-default whenever the iframe is\n // recreated (its key changes). The new render's first binding announcement\n // re-establishes the role.\n useEffect(() => {\n bridgeContextRef.current = { role: \"viewer\", isAuthor: false };\n bindingLatchedRef.current = false;\n readyFiredRef.current = false;\n }, [extensionId, extension?.updatedAt]);\n\n const appearance = useAppearance();\n\n useEffect(() => {\n const win = iframeRef.current?.contentWindow;\n if (!win) return;\n win.postMessage(\n { type: \"agent-native-theme-update\", isDark, vars: readHostThemeVars() },\n \"*\",\n );\n }, [isDark, appearance]);\n\n // Forward slot context whenever it changes. The iframe's own load handler\n // posts the initial value once it's ready; this effect handles updates.\n const contextJson = JSON.stringify(context ?? {});\n useEffect(() => {\n const win = iframeRef.current?.contentWindow;\n if (!win) return;\n win.postMessage(\n { type: \"agent-native-slot-context\", context: context ?? {} },\n \"*\",\n );\n }, [contextJson]);\n\n // Bridge extension requests + height reports.\n useEffect(() => {\n const handleMessage = async (event: MessageEvent) => {\n if (event.source !== iframeRef.current?.contentWindow) return;\n const message = event.data;\n if (!message || typeof message !== \"object\") return;\n\n if (message.type === \"agent-native-extension-binding\") {\n // Only the FIRST announcement (sent by the shell before user content\n // runs) is trusted. Ignore re-announcements — a malicious extension\n // body could otherwise postMessage a forged owner binding to escalate.\n if (bindingLatchedRef.current) return;\n bindingLatchedRef.current = true;\n const binding = (message as any).binding ?? {};\n const role: ExtensionBridgeRole =\n binding.role === \"owner\" ||\n binding.role === \"admin\" ||\n binding.role === \"editor\" ||\n binding.role === \"viewer\"\n ? binding.role\n : \"viewer\";\n bridgeContextRef.current = {\n role,\n isAuthor: !!binding.isAuthor,\n source: binding.source === \"local-files\" ? \"local-files\" : \"database\",\n permissions:\n binding && typeof binding.permissions === \"object\"\n ? binding.permissions\n : undefined,\n };\n return;\n }\n\n if (message.type === \"agent-native-extension-resize\") {\n const h = Number(message.height);\n if (Number.isFinite(h) && h > 0) {\n setHeight(Math.ceil(h));\n // First laid-out height means the content has painted.\n fireReady();\n }\n return;\n }\n\n if (message.type === \"agent-native-send-to-chat\") {\n const text = serializeChatValue((message as any).message);\n if (!text?.trim()) return;\n sendToAgentChat({\n message: text,\n context: serializeChatValue((message as any).context),\n submit: (message as any).submit !== false,\n openSidebar: (message as any).openSidebar !== false,\n });\n return;\n }\n\n if (message.type !== \"agent-native-extension-request\") return;\n\n const requestId = String(message.requestId ?? \"\");\n const path = String(message.path ?? \"\");\n const respond = (payload: Record<string, unknown>) => {\n iframeRef.current?.contentWindow?.postMessage(\n { type: \"agent-native-extension-response\", requestId, ...payload },\n \"*\",\n );\n };\n\n if (!requestId || !isAllowedExtensionPath(path, extensionId)) {\n respond({ error: \"Extension request path is not allowed\" });\n return;\n }\n\n try {\n const options = sanitizeExtensionRequestOptions(message.options);\n // (audit H4) Role-aware gating: viewer-shared extensions can read but not\n // write. The bridge policy is decided here in the parent before the\n // request leaves; the server enforces a second layer.\n const policy = checkBridgePolicy(path, options.method ?? \"GET\", {\n ...bridgeContextRef.current,\n extensionId,\n });\n if (!policy.ok) {\n respond({\n response: {\n ok: false,\n status: 403,\n statusText: \"Forbidden\",\n body: { error: policy.error },\n },\n });\n return;\n }\n // (audit H5) Same extension-bridge tagging as <ExtensionViewer>. action-routes\n // uses these headers to enforce per-action `toolCallable` opt-in.\n const finalHeaders = new Headers(options.headers ?? undefined);\n finalHeaders.set(\"X-Agent-Native-Extension-Bridge\", \"1\");\n finalHeaders.set(\"X-Agent-Native-Extension-Id\", extensionId);\n finalHeaders.set(\"X-Agent-Native-Tool-Bridge\", \"1\");\n finalHeaders.set(\"X-Agent-Native-Tool-Id\", extensionId);\n const res = await fetch(agentNativePath(path), {\n ...options,\n headers: finalHeaders,\n credentials: \"same-origin\",\n });\n const text = await res.text();\n let body: unknown = text;\n if (text) {\n try {\n body = JSON.parse(text);\n } catch {\n body = text;\n }\n }\n respond({\n response: {\n ok: res.ok,\n status: res.status,\n statusText: res.statusText,\n body,\n },\n });\n } catch (err: any) {\n respond({ error: err?.message ?? \"Extension host request failed\" });\n }\n };\n\n window.addEventListener(\"message\", handleMessage);\n return () => window.removeEventListener(\"message\", handleMessage);\n }, [extensionId]);\n\n if (!extension) {\n if (!isLoading && !isFetching) return null;\n return (\n <div\n className={className}\n style={{ height: initialHeight }}\n aria-busy=\"true\"\n />\n );\n }\n\n return (\n <div className={`relative group/embedded-extension ${className ?? \"\"}`}>\n <iframe\n ref={iframeRef}\n key={`${extensionId}-${extension.updatedAt ?? \"\"}`}\n src={iframeSrc}\n title={extension.name}\n sandbox={EXTENSION_IFRAME_SANDBOX}\n style={{ width: \"100%\", border: 0, height, display: \"block\" }}\n onLoad={() => {\n iframeRef.current?.contentWindow?.postMessage(\n { type: \"agent-native-slot-context\", context: context ?? {} },\n \"*\",\n );\n // Re-assert theme once the iframe document is live. The src bakes in\n // the initial dark state, but this covers the race where isDark\n // settled before the iframe's message listener existed.\n iframeRef.current?.contentWindow?.postMessage(\n {\n type: \"agent-native-theme-update\",\n isDark,\n vars: readHostThemeVars(),\n },\n \"*\",\n );\n // Fallback readiness signal in case the extension never reports a\n // height (e.g. fixed-height content that skips auto-resize).\n fireReady();\n }}\n />\n <EmbeddedToolMenu\n extensionId={extensionId}\n slotId={slotId}\n toolName={extension.name}\n canDelete={extension.canDelete}\n />\n </div>\n );\n}\n\nfunction EmbeddedToolMenu({\n extensionId,\n slotId,\n toolName,\n canDelete,\n}: {\n extensionId: string;\n slotId: string;\n toolName: string;\n canDelete?: boolean;\n}) {\n const t = useT();\n const [open, setOpen] = useState(false);\n const [confirmingDelete, setConfirmingDelete] = useState(false);\n const queryClient = useQueryClient();\n const navigate = useNavigate();\n\n const closeMenu = () => {\n setOpen(false);\n setConfirmingDelete(false);\n };\n\n const removeFromSlot = async () => {\n closeMenu();\n queryClient.setQueryData<any[]>([\"slot-installs\", slotId], (old) =>\n (old ?? []).filter((i) => i.extensionId !== extensionId),\n );\n try {\n await fetch(\n agentNativePath(\n `/_agent-native/slots/${encodeURIComponent(slotId)}/install/${encodeURIComponent(extensionId)}`,\n ),\n { method: \"DELETE\" },\n );\n } finally {\n queryClient.invalidateQueries({ queryKey: [\"slot-installs\", slotId] });\n }\n };\n\n const deleteExtension = async () => {\n closeMenu();\n try {\n await deleteOrHideExtension({ id: extensionId, canDelete });\n invalidateExtensionRemoval(queryClient, extensionId);\n } catch {\n queryClient.invalidateQueries({ queryKey: [\"extension\", extensionId] });\n }\n };\n\n return (\n <Popover\n open={open}\n onOpenChange={(o) => {\n setOpen(o);\n if (!o) setConfirmingDelete(false);\n }}\n >\n <TooltipProvider delayDuration={200}>\n <Tooltip>\n <TooltipTrigger asChild>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"absolute top-1 right-1 flex h-6 w-6 items-center justify-center rounded-md bg-background/60 text-muted-foreground/60 opacity-0 hover:bg-accent hover:text-foreground hover:opacity-100 group-hover/embedded-extension:opacity-100 cursor-pointer transition-opacity\"\n aria-label={t(\"extensions.optionsFor\", { name: toolName })}\n >\n <IconDots className=\"h-3.5 w-3.5\" />\n </button>\n </PopoverTrigger>\n </TooltipTrigger>\n <TooltipContent>\n {t(\"extensions.optionsFor\", { name: toolName })}\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n <PopoverContent align=\"end\" sideOffset={4} className=\"w-56 p-1\">\n {!confirmingDelete ? (\n <div className=\"flex flex-col\">\n <button\n type=\"button\"\n onClick={() => {\n closeMenu();\n navigate(extensionPath(extensionId, toolName));\n }}\n className=\"flex items-center gap-2 rounded-sm px-2 py-1.5 text-[12px] hover:bg-accent cursor-pointer text-left\"\n >\n <IconExternalLink className=\"h-3.5 w-3.5\" />\n <span>{t(\"extensions.openFullView\")}</span>\n </button>\n <button\n type=\"button\"\n onClick={removeFromSlot}\n className=\"flex items-center gap-2 rounded-sm px-2 py-1.5 text-[12px] hover:bg-accent cursor-pointer text-left\"\n >\n <IconLayoutSidebarRightCollapse className=\"h-3.5 w-3.5\" />\n <span>{t(\"extensions.removeFromWidgetArea\")}</span>\n </button>\n {canDelete !== false && (\n <>\n <div className=\"my-1 h-px bg-border/40\" />\n <button\n type=\"button\"\n onClick={() => setConfirmingDelete(true)}\n className=\"flex items-center gap-2 rounded-sm px-2 py-1.5 text-[12px] text-destructive hover:bg-destructive/10 cursor-pointer text-left\"\n >\n <IconTrash className=\"h-3.5 w-3.5\" />\n <span>{t(\"extensions.deleteExtensionEllipsis\")}</span>\n </button>\n </>\n )}\n </div>\n ) : (\n <div className=\"flex flex-col gap-2 p-2\">\n <p className=\"text-[12px]\">\n {t(\"extensions.deleteQuestion\", { name: toolName })}{\" \"}\n {t(\"extensions.deleteEverywhereConfirmation\")}\n </p>\n <div className=\"flex justify-end gap-1\">\n <button\n type=\"button\"\n onClick={() => setConfirmingDelete(false)}\n className=\"rounded-md px-2 py-1 text-[12px] hover:bg-accent cursor-pointer\"\n >\n {t(\"extensions.cancel\")}\n </button>\n <button\n type=\"button\"\n onClick={deleteExtension}\n className=\"rounded-md bg-destructive px-2 py-1 text-[12px] text-destructive-foreground hover:bg-destructive/90 cursor-pointer\"\n >\n {t(\"extensions.delete\")}\n </button>\n </div>\n </div>\n )}\n </PopoverContent>\n </Popover>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ExtensionViewer.d.ts","sourceRoot":"","sources":["../../../src/client/extensions/ExtensionViewer.tsx"],"names":[],"mappings":"AAiHA,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;CACrB;AA0oBD,wBAAgB,eAAe,CAAC,EAAE,WAAW,EAAE,EAAE,oBAAoB,+BAykBpE"}
1
+ {"version":3,"file":"ExtensionViewer.d.ts","sourceRoot":"","sources":["../../../src/client/extensions/ExtensionViewer.tsx"],"names":[],"mappings":"AAqHA,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;CACrB;AA4qBD,wBAAgB,eAAe,CAAC,EAAE,WAAW,EAAE,EAAE,oBAAoB,+BAglBpE"}