@agent-native/core 0.90.10 → 0.91.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (360) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +30 -0
  3. package/corpus/core/docs/content/toolkit-settings.mdx +56 -3
  4. package/corpus/core/package.json +2 -1
  5. package/corpus/core/src/agent/durable-background.ts +5 -5
  6. package/corpus/core/src/agent/engine/ai-sdk-engine.ts +40 -8
  7. package/corpus/core/src/agent/engine/anthropic-engine.ts +25 -7
  8. package/corpus/core/src/agent/engine/output-tokens.ts +94 -0
  9. package/corpus/core/src/agent/production-agent.ts +34 -6
  10. package/corpus/core/src/agent/run-ownership.ts +29 -1
  11. package/corpus/core/src/agent/types.ts +3 -2
  12. package/corpus/core/src/changelog/parse.ts +78 -0
  13. package/corpus/core/src/chat-threads/schema.ts +43 -0
  14. package/corpus/core/src/chat-threads/store.ts +144 -12
  15. package/corpus/core/src/cli/workspace-dev.ts +25 -5
  16. package/corpus/core/src/client/AgentPanel.tsx +79 -14
  17. package/corpus/core/src/client/AssistantChat.tsx +359 -425
  18. package/corpus/core/src/client/analytics-session.ts +70 -0
  19. package/corpus/core/src/client/analytics.ts +175 -49
  20. package/corpus/core/src/client/chat/message-components.tsx +22 -2
  21. package/corpus/core/src/client/components/ui/message-scroller.tsx +131 -0
  22. package/corpus/core/src/client/conversation/AgentConversation.tsx +63 -41
  23. package/corpus/core/src/client/error-capture.ts +616 -0
  24. package/corpus/core/src/client/index.ts +12 -0
  25. package/corpus/core/src/client/session-replay.ts +57 -7
  26. package/corpus/core/src/client/settings/SettingsPanel.tsx +123 -1
  27. package/corpus/core/src/client/settings/SettingsTabsPage.tsx +292 -45
  28. package/corpus/core/src/client/settings/index.ts +1 -0
  29. package/corpus/core/src/client/sharing/ShareButton.tsx +14 -11
  30. package/corpus/core/src/client/sharing/ShareDialog.tsx +13 -10
  31. package/corpus/core/src/db/client.ts +12 -9
  32. package/corpus/core/src/mcp/builtin-tools.ts +29 -2
  33. package/corpus/core/src/server/agent-chat-plugin.ts +174 -79
  34. package/corpus/core/src/server/onboarding-html.ts +28 -16
  35. package/corpus/core/src/shared/reasoning-effort.ts +23 -0
  36. package/corpus/core/src/sharing/actions/list-resource-shares.ts +45 -1
  37. package/corpus/core/src/sharing/actions/share-resource.ts +9 -0
  38. package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -2
  39. package/corpus/core/src/templates/workspace-core/.agents/skills/changelog/SKILL.md +9 -6
  40. package/corpus/core/src/vite/client.ts +217 -35
  41. package/corpus/templates/analytics/.agents/skills/adhoc-analysis/SKILL.md +8 -7
  42. package/corpus/templates/analytics/.agents/skills/analysis-workspace/SKILL.md +14 -10
  43. package/corpus/templates/analytics/.agents/skills/bigquery/SKILL.md +15 -15
  44. package/corpus/templates/analytics/.agents/skills/cross-source-analysis/SKILL.md +1 -0
  45. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +38 -22
  46. package/corpus/templates/analytics/.agents/skills/data-programs/SKILL.md +114 -61
  47. package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +1 -0
  48. package/corpus/templates/analytics/.agents/skills/gong/SKILL.md +7 -7
  49. package/corpus/templates/analytics/.agents/skills/hubspot/SKILL.md +1 -0
  50. package/corpus/templates/analytics/.agents/skills/prometheus/SKILL.md +1 -1
  51. package/corpus/templates/analytics/.builder/skills/bigquery/SKILL.md +17 -17
  52. package/corpus/templates/analytics/.builder/skills/gcloud/SKILL.md +5 -5
  53. package/corpus/templates/analytics/.builder/skills/github/SKILL.md +7 -7
  54. package/corpus/templates/analytics/.builder/skills/gong/SKILL.md +12 -12
  55. package/corpus/templates/analytics/.builder/skills/grafana/SKILL.md +7 -7
  56. package/corpus/templates/analytics/.builder/skills/sentry/SKILL.md +7 -7
  57. package/corpus/templates/analytics/.builder/skills/slack/SKILL.md +6 -6
  58. package/corpus/templates/analytics/.builder/skills/stripe/SKILL.md +7 -7
  59. package/corpus/templates/analytics/AGENTS.md +47 -2
  60. package/corpus/templates/analytics/actions/add-status-page-monitor.ts +36 -0
  61. package/corpus/templates/analytics/actions/capture-test-error.ts +33 -0
  62. package/corpus/templates/analytics/actions/delete-monitor.ts +24 -0
  63. package/corpus/templates/analytics/actions/delete-status-page.ts +23 -0
  64. package/corpus/templates/analytics/actions/get-error-issue.ts +36 -0
  65. package/corpus/templates/analytics/actions/get-monitor-stats.ts +55 -0
  66. package/corpus/templates/analytics/actions/get-monitor.ts +27 -0
  67. package/corpus/templates/analytics/actions/get-public-status-page.ts +41 -0
  68. package/corpus/templates/analytics/actions/get-status-page.ts +29 -0
  69. package/corpus/templates/analytics/actions/list-error-issues.ts +40 -0
  70. package/corpus/templates/analytics/actions/list-monitors.ts +21 -0
  71. package/corpus/templates/analytics/actions/list-status-pages.ts +21 -0
  72. package/corpus/templates/analytics/actions/match-error-issues.ts +51 -0
  73. package/corpus/templates/analytics/actions/navigate.ts +58 -4
  74. package/corpus/templates/analytics/actions/remove-status-page-monitor.ts +22 -0
  75. package/corpus/templates/analytics/actions/reorder-status-page-monitors.ts +25 -0
  76. package/corpus/templates/analytics/actions/resolve-error-issue.ts +38 -0
  77. package/corpus/templates/analytics/actions/run-monitor-check.ts +23 -0
  78. package/corpus/templates/analytics/actions/save-analysis.ts +1 -0
  79. package/corpus/templates/analytics/actions/save-monitor.ts +145 -0
  80. package/corpus/templates/analytics/actions/save-status-page.ts +47 -0
  81. package/corpus/templates/analytics/actions/view-screen.ts +212 -0
  82. package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -0
  83. package/corpus/templates/analytics/app/components/layout/Layout.tsx +10 -1
  84. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +134 -39
  85. package/corpus/templates/analytics/app/components/monitoring/PublicStatusView.tsx +351 -0
  86. package/corpus/templates/analytics/app/components/monitoring/ResponseTimeChart.tsx +174 -0
  87. package/corpus/templates/analytics/app/components/monitoring/UptimeStatCards.tsx +85 -0
  88. package/corpus/templates/analytics/app/components/monitoring/UptimeTimelineBars.tsx +106 -0
  89. package/corpus/templates/analytics/app/components/monitoring/chart-utils.ts +101 -0
  90. package/corpus/templates/analytics/app/components/monitoring/index.ts +28 -0
  91. package/corpus/templates/analytics/app/components/monitoring/types.ts +42 -0
  92. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +34 -0
  93. package/corpus/templates/analytics/app/i18n/zh-TW.ts +6 -0
  94. package/corpus/templates/analytics/app/i18n-data.ts +33 -0
  95. package/corpus/templates/analytics/app/pages/DataSources.tsx +28 -0
  96. package/corpus/templates/analytics/app/pages/Settings.tsx +77 -9
  97. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +3 -3
  98. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/dashboard-layout.ts +7 -0
  99. package/corpus/templates/analytics/app/pages/monitoring/ErrorsPanel.tsx +205 -0
  100. package/corpus/templates/analytics/app/pages/monitoring/MonitoringPage.tsx +100 -0
  101. package/corpus/templates/analytics/app/pages/monitoring/UptimePanel.tsx +475 -0
  102. package/corpus/templates/analytics/app/pages/monitoring/errors/IssueDetail.tsx +372 -0
  103. package/corpus/templates/analytics/app/pages/monitoring/errors/IssueList.tsx +360 -0
  104. package/corpus/templates/analytics/app/pages/monitoring/errors/Sparkline.tsx +55 -0
  105. package/corpus/templates/analytics/app/pages/monitoring/errors/i18n.ts +106 -0
  106. package/corpus/templates/analytics/app/pages/monitoring/errors/types.ts +75 -0
  107. package/corpus/templates/analytics/app/pages/monitoring/errors/utils.ts +132 -0
  108. package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorDetail.tsx +535 -0
  109. package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorFormPage.tsx +1026 -0
  110. package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorList.tsx +311 -0
  111. package/corpus/templates/analytics/app/pages/monitoring/uptime/i18n.ts +235 -0
  112. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/StatusPageEditor.tsx +661 -0
  113. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/StatusPagesView.tsx +355 -0
  114. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/i18n.ts +106 -0
  115. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/slug.ts +24 -0
  116. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/types.ts +20 -0
  117. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-summary.ts +87 -0
  118. package/corpus/templates/analytics/app/pages/monitoring/uptime/types.ts +161 -0
  119. package/corpus/templates/analytics/app/pages/monitoring/uptime/utils.ts +210 -0
  120. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +76 -1
  121. package/corpus/templates/analytics/app/pages/sessions/SessionDevToolsPanel.tsx +74 -9
  122. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +197 -20
  123. package/corpus/templates/analytics/app/root.tsx +33 -1
  124. package/corpus/templates/analytics/app/routes/monitoring._index.tsx +10 -0
  125. package/corpus/templates/analytics/app/routes/status.$slug.tsx +118 -0
  126. package/corpus/templates/analytics/changelog/2026-07-08-add-uptime-monitors-that-ping-your-urls-and-alert-you-when-t.md +6 -0
  127. package/corpus/templates/analytics/changelog/2026-07-08-analytics-chats-keep-large-data-dictionaries-compact-so-prov.md +6 -0
  128. package/corpus/templates/analytics/changelog/2026-07-08-create-public-status-pages-that-share-the-live-health-of-cho.md +6 -0
  129. package/corpus/templates/analytics/changelog/2026-07-08-dashboard-extension-panels-use-clearer-open-copy.md +6 -0
  130. package/corpus/templates/analytics/changelog/2026-07-08-error-capture.md +6 -0
  131. package/corpus/templates/analytics/changelog/2026-07-08-fixed-single-panel-dashboard-drags-so-they-no-longer-rewrite.md +6 -0
  132. package/corpus/templates/analytics/changelog/2026-07-08-jump-straight-from-an-error-in-a-session-recording-to-its-fu.md +6 -0
  133. package/corpus/templates/analytics/changelog/2026-07-08-monitor-detail-and-list-now-show-colorful-uptime-timelines-r.md +6 -0
  134. package/corpus/templates/analytics/changelog/2026-07-08-pinned-ask-chats-now-show-a-pin-icon-in-the-sidebar.md +6 -0
  135. package/corpus/templates/analytics/changelog/2026-07-08-publish-a-public-uptime-status-page-with-colorful-uptime-tim.md +6 -0
  136. package/corpus/templates/analytics/changelog/2026-07-08-sessions-now-hide-visitor-emails-in-demo-mode-and-show-clean.md +6 -0
  137. package/corpus/templates/analytics/changelog/2026-07-08-settings-are-cleaner-searchable-and-alerts-have-their-own-tab.md +5 -0
  138. package/corpus/templates/analytics/changelog/2026-07-08-sidebar-sections-stay-collapsed-until-opened.md +5 -0
  139. package/corpus/templates/analytics/changelog/2026-07-08-the-uptime-monitor-list-now-has-a-current-status-overview-wi.md +6 -0
  140. package/corpus/templates/analytics/docs/error-capture.md +172 -0
  141. package/corpus/templates/analytics/docs/uptime-monitoring.md +150 -0
  142. package/corpus/templates/analytics/server/db/schema-errors.ts +150 -0
  143. package/corpus/templates/analytics/server/db/schema-monitoring.ts +177 -0
  144. package/corpus/templates/analytics/server/db/schema.ts +6 -0
  145. package/corpus/templates/analytics/server/jobs/uptime-monitors.ts +123 -0
  146. package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +41 -0
  147. package/corpus/templates/analytics/server/lib/data-dictionary-context.ts +55 -12
  148. package/corpus/templates/analytics/server/lib/error-capture.ts +1331 -0
  149. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +47 -1
  150. package/corpus/templates/analytics/server/lib/monitor-stats.ts +494 -0
  151. package/corpus/templates/analytics/server/lib/status-pages.ts +798 -0
  152. package/corpus/templates/analytics/server/lib/uptime-monitors.ts +1665 -0
  153. package/corpus/templates/analytics/server/plugins/agent-chat.ts +7 -37
  154. package/corpus/templates/analytics/server/plugins/auth.ts +11 -1
  155. package/corpus/templates/analytics/server/plugins/db.ts +408 -0
  156. package/corpus/templates/analytics/server/plugins/uptime-monitor-jobs.ts +63 -0
  157. package/corpus/templates/assets/app/routes/_index.tsx +1 -1
  158. package/corpus/templates/assets/app/routes/settings.tsx +22 -1
  159. package/corpus/templates/assets/changelog/2026-07-08-recent-drafts-keep-comfortable-side-padding.md +6 -0
  160. package/corpus/templates/assets/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  161. package/corpus/templates/brain/app/routes/settings.tsx +43 -5
  162. package/corpus/templates/brain/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  163. package/corpus/templates/calendar/app/pages/Settings.tsx +44 -6
  164. package/corpus/templates/calendar/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  165. package/corpus/templates/chat/app/routes/settings.tsx +16 -1
  166. package/corpus/templates/chat/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  167. package/corpus/templates/clips/actions/lib/audio-only-transcription.ts +79 -37
  168. package/corpus/templates/clips/actions/regenerate-chapters.ts +7 -0
  169. package/corpus/templates/clips/app/components/player/player-controls.tsx +35 -0
  170. package/corpus/templates/clips/app/components/player/video-player.tsx +162 -18
  171. package/corpus/templates/clips/app/hooks/use-auto-title.ts +15 -5
  172. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +63 -6
  173. package/corpus/templates/clips/app/routes/download.tsx +12 -4
  174. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +1 -0
  175. package/corpus/templates/clips/app/routes/record.tsx +18 -1
  176. package/corpus/templates/clips/changelog/2026-07-07-auto-generated-chapter-requests-now-open-the-matching-agent-.md +6 -0
  177. package/corpus/templates/clips/changelog/2026-07-07-shared-clips-start-playback-reliably-from-the-first-play-click.md +6 -0
  178. package/corpus/templates/clips/changelog/2026-07-07-the-clips-desktop-download-page-now-uses-the-agent-native-ap.md +6 -0
  179. package/corpus/templates/clips/changelog/2026-07-08-chrome-extension-camera-and-microphone-menus-now-show-which-.md +6 -0
  180. package/corpus/templates/clips/changelog/2026-07-08-chrome-extension-copies-new-clip-links-after-saving.md +6 -0
  181. package/corpus/templates/clips/changelog/2026-07-08-chrome-extension-recordings-now-continue-after-granting-came.md +6 -0
  182. package/corpus/templates/clips/changelog/2026-07-08-mobile-shared-clips-now-have-loom-style-tap-and-skip-controls.md +6 -0
  183. package/corpus/templates/clips/changelog/2026-07-08-recordings-and-uploads-copy-links-after-saving.md +6 -0
  184. package/corpus/templates/clips/changelog/2026-07-08-settings-are-cleaner-searchable-and-collapse-s3-with-builder.md +5 -0
  185. package/corpus/templates/clips/changelog/2026-07-08-transcripts-are-more-reliable-for-longer-desktop-recordings-.md +6 -0
  186. package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -0
  187. package/corpus/templates/clips/chrome-extension/src/background.ts +162 -13
  188. package/corpus/templates/clips/chrome-extension/src/content-script.ts +14 -0
  189. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +36 -0
  190. package/corpus/templates/clips/chrome-extension/src/overlay.ts +99 -25
  191. package/corpus/templates/clips/chrome-extension/src/permission.ts +63 -14
  192. package/corpus/templates/clips/chrome-extension/src/popup.ts +123 -23
  193. package/corpus/templates/content/actions/_builder-cms-read-client.ts +47 -0
  194. package/corpus/templates/content/actions/_database-source-utils.ts +33 -4
  195. package/corpus/templates/content/actions/add-content-database-source-field-property.ts +214 -29
  196. package/corpus/templates/content/actions/attach-content-database-source.ts +3 -0
  197. package/corpus/templates/content/actions/change-content-database-source-role.ts +1 -0
  198. package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +42 -32
  199. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +352 -81
  200. package/corpus/templates/content/app/components/editor/database/settings.tsx +49 -24
  201. package/corpus/templates/content/app/routes/_app.settings.tsx +19 -1
  202. package/corpus/templates/content/changelog/2026-07-07-builder-source-tag-fields-now-import-as-multi-select.md +6 -0
  203. package/corpus/templates/content/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  204. package/corpus/templates/content/shared/api.ts +3 -0
  205. package/corpus/templates/content/shared/properties.ts +42 -0
  206. package/corpus/templates/design/actions/generate-design.ts +3 -0
  207. package/corpus/templates/design/actions/get-design-system.ts +147 -1
  208. package/corpus/templates/design/app/routes/settings.tsx +16 -1
  209. package/corpus/templates/design/changelog/2026-07-08-design-generation-now-follows-hydrated-builder-design-system.md +6 -0
  210. package/corpus/templates/design/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  211. package/corpus/templates/dispatch/app/routes/settings.tsx +23 -2
  212. package/corpus/templates/dispatch/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  213. package/corpus/templates/forms/app/routes/_app.settings.tsx +16 -1
  214. package/corpus/templates/forms/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  215. package/corpus/templates/macros/app/routes/settings.tsx +16 -1
  216. package/corpus/templates/macros/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  217. package/corpus/templates/mail/app/components/settings/GmailFiltersSection.tsx +1 -1
  218. package/corpus/templates/mail/app/components/settings/SnippetsSection.tsx +1 -1
  219. package/corpus/templates/mail/app/pages/SettingsPage.tsx +123 -105
  220. package/corpus/templates/mail/changelog/2026-07-08-settings-redesigned-with-a-consistent-searchable-layout.md +5 -0
  221. package/corpus/templates/plan/app/routes/settings.tsx +23 -2
  222. package/corpus/templates/plan/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  223. package/corpus/templates/slides/actions/add-slide.ts +1 -0
  224. package/corpus/templates/slides/actions/get-design-system.ts +147 -1
  225. package/corpus/templates/slides/app/pages/Index.tsx +46 -1
  226. package/corpus/templates/slides/app/routes/settings.tsx +16 -1
  227. package/corpus/templates/slides/changelog/2026-07-08-deck-generation-now-follows-hydrated-builder-design-system-g.md +6 -0
  228. package/corpus/templates/slides/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  229. package/dist/agent/durable-background.d.ts +1 -1
  230. package/dist/agent/durable-background.d.ts.map +1 -1
  231. package/dist/agent/durable-background.js +5 -3
  232. package/dist/agent/durable-background.js.map +1 -1
  233. package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
  234. package/dist/agent/engine/ai-sdk-engine.js +24 -4
  235. package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
  236. package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
  237. package/dist/agent/engine/anthropic-engine.js +13 -3
  238. package/dist/agent/engine/anthropic-engine.js.map +1 -1
  239. package/dist/agent/engine/output-tokens.d.ts +27 -0
  240. package/dist/agent/engine/output-tokens.d.ts.map +1 -1
  241. package/dist/agent/engine/output-tokens.js +70 -0
  242. package/dist/agent/engine/output-tokens.js.map +1 -1
  243. package/dist/agent/production-agent.d.ts.map +1 -1
  244. package/dist/agent/production-agent.js +28 -7
  245. package/dist/agent/production-agent.js.map +1 -1
  246. package/dist/agent/run-ownership.d.ts +6 -0
  247. package/dist/agent/run-ownership.d.ts.map +1 -1
  248. package/dist/agent/run-ownership.js +11 -1
  249. package/dist/agent/run-ownership.js.map +1 -1
  250. package/dist/agent/types.d.ts +3 -2
  251. package/dist/agent/types.d.ts.map +1 -1
  252. package/dist/agent/types.js.map +1 -1
  253. package/dist/changelog/parse.d.ts +7 -0
  254. package/dist/changelog/parse.d.ts.map +1 -1
  255. package/dist/changelog/parse.js +64 -0
  256. package/dist/changelog/parse.js.map +1 -1
  257. package/dist/chat-threads/schema.d.ts +445 -0
  258. package/dist/chat-threads/schema.d.ts.map +1 -0
  259. package/dist/chat-threads/schema.js +39 -0
  260. package/dist/chat-threads/schema.js.map +1 -0
  261. package/dist/chat-threads/store.d.ts +12 -0
  262. package/dist/chat-threads/store.d.ts.map +1 -1
  263. package/dist/chat-threads/store.js +99 -10
  264. package/dist/chat-threads/store.js.map +1 -1
  265. package/dist/cli/workspace-dev.d.ts.map +1 -1
  266. package/dist/cli/workspace-dev.js +20 -5
  267. package/dist/cli/workspace-dev.js.map +1 -1
  268. package/dist/client/AgentPanel.d.ts.map +1 -1
  269. package/dist/client/AgentPanel.js +35 -7
  270. package/dist/client/AgentPanel.js.map +1 -1
  271. package/dist/client/AssistantChat.d.ts.map +1 -1
  272. package/dist/client/AssistantChat.js +105 -183
  273. package/dist/client/AssistantChat.js.map +1 -1
  274. package/dist/client/analytics-session.d.ts +3 -0
  275. package/dist/client/analytics-session.d.ts.map +1 -0
  276. package/dist/client/analytics-session.js +66 -0
  277. package/dist/client/analytics-session.js.map +1 -0
  278. package/dist/client/analytics.d.ts +32 -0
  279. package/dist/client/analytics.d.ts.map +1 -1
  280. package/dist/client/analytics.js +116 -46
  281. package/dist/client/analytics.js.map +1 -1
  282. package/dist/client/chat/message-components.d.ts +2 -1
  283. package/dist/client/chat/message-components.d.ts.map +1 -1
  284. package/dist/client/chat/message-components.js +16 -6
  285. package/dist/client/chat/message-components.js.map +1 -1
  286. package/dist/client/components/ui/message-scroller.d.ts +16 -0
  287. package/dist/client/components/ui/message-scroller.d.ts.map +1 -0
  288. package/dist/client/components/ui/message-scroller.js +25 -0
  289. package/dist/client/components/ui/message-scroller.js.map +1 -0
  290. package/dist/client/conversation/AgentConversation.d.ts +1 -1
  291. package/dist/client/conversation/AgentConversation.d.ts.map +1 -1
  292. package/dist/client/conversation/AgentConversation.js +3 -8
  293. package/dist/client/conversation/AgentConversation.js.map +1 -1
  294. package/dist/client/error-capture.d.ts +99 -0
  295. package/dist/client/error-capture.d.ts.map +1 -0
  296. package/dist/client/error-capture.js +437 -0
  297. package/dist/client/error-capture.js.map +1 -0
  298. package/dist/client/index.d.ts +2 -2
  299. package/dist/client/index.d.ts.map +1 -1
  300. package/dist/client/index.js +3 -1
  301. package/dist/client/index.js.map +1 -1
  302. package/dist/client/session-replay.d.ts +22 -0
  303. package/dist/client/session-replay.d.ts.map +1 -1
  304. package/dist/client/session-replay.js +45 -4
  305. package/dist/client/session-replay.js.map +1 -1
  306. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  307. package/dist/client/settings/SettingsPanel.js +100 -5
  308. package/dist/client/settings/SettingsPanel.js.map +1 -1
  309. package/dist/client/settings/SettingsTabsPage.d.ts +49 -1
  310. package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -1
  311. package/dist/client/settings/SettingsTabsPage.js +131 -19
  312. package/dist/client/settings/SettingsTabsPage.js.map +1 -1
  313. package/dist/client/settings/index.d.ts +1 -1
  314. package/dist/client/settings/index.d.ts.map +1 -1
  315. package/dist/client/settings/index.js.map +1 -1
  316. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  317. package/dist/client/sharing/ShareButton.js +13 -8
  318. package/dist/client/sharing/ShareButton.js.map +1 -1
  319. package/dist/client/sharing/ShareDialog.d.ts.map +1 -1
  320. package/dist/client/sharing/ShareDialog.js +12 -7
  321. package/dist/client/sharing/ShareDialog.js.map +1 -1
  322. package/dist/collab/routes.d.ts +1 -1
  323. package/dist/collab/struct-routes.d.ts +1 -1
  324. package/dist/db/client.d.ts.map +1 -1
  325. package/dist/db/client.js +12 -7
  326. package/dist/db/client.js.map +1 -1
  327. package/dist/mcp/builtin-tools.d.ts.map +1 -1
  328. package/dist/mcp/builtin-tools.js +21 -2
  329. package/dist/mcp/builtin-tools.js.map +1 -1
  330. package/dist/notifications/routes.d.ts +1 -1
  331. package/dist/observability/routes.d.ts +5 -5
  332. package/dist/org/schema.d.ts +15 -15
  333. package/dist/progress/routes.d.ts +1 -1
  334. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  335. package/dist/resources/handlers.d.ts +3 -3
  336. package/dist/secrets/routes.d.ts +9 -9
  337. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  338. package/dist/server/agent-chat-plugin.js +109 -73
  339. package/dist/server/agent-chat-plugin.js.map +1 -1
  340. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  341. package/dist/server/onboarding-html.d.ts.map +1 -1
  342. package/dist/server/onboarding-html.js +28 -16
  343. package/dist/server/onboarding-html.js.map +1 -1
  344. package/dist/shared/reasoning-effort.d.ts +1 -0
  345. package/dist/shared/reasoning-effort.d.ts.map +1 -1
  346. package/dist/shared/reasoning-effort.js +18 -0
  347. package/dist/shared/reasoning-effort.js.map +1 -1
  348. package/dist/sharing/actions/list-resource-shares.js +30 -1
  349. package/dist/sharing/actions/list-resource-shares.js.map +1 -1
  350. package/dist/sharing/actions/share-resource.js +6 -0
  351. package/dist/sharing/actions/share-resource.js.map +1 -1
  352. package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -2
  353. package/dist/templates/workspace-core/.agents/skills/changelog/SKILL.md +9 -6
  354. package/dist/vite/client.d.ts.map +1 -1
  355. package/dist/vite/client.js +192 -30
  356. package/dist/vite/client.js.map +1 -1
  357. package/docs/content/toolkit-settings.mdx +56 -3
  358. package/package.json +2 -1
  359. package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -2
  360. package/src/templates/workspace-core/.agents/skills/changelog/SKILL.md +9 -6
@@ -0,0 +1,616 @@
1
+ /**
2
+ * First-party, Sentry-style browser error capture for the Agent Native
3
+ * analytics SDK.
4
+ *
5
+ * Two responsibilities:
6
+ * 1. Automatic capture of uncaught exceptions (`window.onerror`) and
7
+ * unhandled promise rejections (`unhandledrejection`).
8
+ * 2. A documented manual API — `captureException(error, context?)` and
9
+ * `captureMessage(message, level?)` — mirroring Sentry's ergonomics.
10
+ *
11
+ * Captured exceptions are handed to a `send` callback (wired by
12
+ * `configureTracking` to the first-party analytics `/track` ingest as a
13
+ * dedicated `$exception` event) and are tagged with the current analytics
14
+ * session id + session replay id so each error links back to the recording it
15
+ * happened in. Everything here is defensive: capture must never throw back into
16
+ * the host app, so every path is wrapped and failures are swallowed.
17
+ *
18
+ * Stack parsing and fingerprinting are intentionally done authoritatively on
19
+ * the server (see the analytics template's `server/lib/error-capture.ts`); the
20
+ * client sends a compact, bounded payload (type/message/raw stack/context) and
21
+ * the server normalizes + groups it. That keeps one tested source of truth for
22
+ * grouping instead of duplicating parser logic across the wire.
23
+ */
24
+ import { scrubUrl } from "./url-scrub.js";
25
+
26
+ export type ExceptionLevel = "fatal" | "error" | "warning" | "info" | "debug";
27
+
28
+ /** Extra Sentry-style context accepted by `captureException`. */
29
+ export interface CaptureExceptionContext {
30
+ /** Low-cardinality searchable tags. Values are coerced to strings. */
31
+ tags?: Record<string, string | number | boolean | null | undefined>;
32
+ /** Structured, higher-cardinality detail shown on the event. */
33
+ extra?: Record<string, unknown>;
34
+ /** Severity; defaults to "error". */
35
+ level?: ExceptionLevel;
36
+ }
37
+
38
+ export interface ExceptionBreadcrumb {
39
+ timestamp: string;
40
+ category: string;
41
+ message: string;
42
+ level?: ExceptionLevel;
43
+ }
44
+
45
+ /**
46
+ * Compact exception payload emitted to transport. Field names are the wire
47
+ * contract the analytics server ingest reads — keep them stable.
48
+ */
49
+ export interface CapturedExceptionEvent {
50
+ /** Error class/name, e.g. "TypeError". "Message" for `captureMessage`. */
51
+ type: string;
52
+ message: string;
53
+ /** Raw (bounded, redacted) stack string; server parses it into frames. */
54
+ stack?: string;
55
+ /** False for uncaught/global errors, true for manually handled ones. */
56
+ handled: boolean;
57
+ level: ExceptionLevel;
58
+ /** ISO timestamp of the occurrence. */
59
+ occurredAt: string;
60
+ url?: string;
61
+ release?: string;
62
+ environment?: string;
63
+ sessionId?: string;
64
+ /** Client session replay id (localStorage) for replay linkage. */
65
+ sessionReplayId?: string;
66
+ anonymousId?: string;
67
+ breadcrumbs: ExceptionBreadcrumb[];
68
+ tags?: Record<string, string>;
69
+ extra?: Record<string, unknown>;
70
+ }
71
+
72
+ export interface InstallErrorCaptureOptions {
73
+ /** Transport for a captured exception. Must not throw. */
74
+ send: (event: CapturedExceptionEvent) => void;
75
+ /** Resolve current analytics/session-replay identifiers at capture time. */
76
+ getSessionContext?: () => {
77
+ sessionId?: string;
78
+ anonymousId?: string;
79
+ replayId?: string;
80
+ };
81
+ /**
82
+ * Optional hook to also surface a manual capture on the session replay
83
+ * timeline. Only invoked for manual `captureException`/`captureMessage`;
84
+ * auto-captured global errors are already recorded by the replay recorder.
85
+ */
86
+ emitReplayEvent?: (event: CapturedExceptionEvent) => void;
87
+ release?: string;
88
+ environment?: string;
89
+ /** Auto-capture `window.onerror`. Defaults to true. */
90
+ captureGlobalErrors?: boolean;
91
+ /** Auto-capture `unhandledrejection`. Defaults to true. */
92
+ captureUnhandledRejections?: boolean;
93
+ /** Breadcrumb ring buffer size. Defaults to 20. */
94
+ maxBreadcrumbs?: number;
95
+ /** Dedupe window (ms) for identical signatures. Defaults to 3000. */
96
+ dedupeWindowMs?: number;
97
+ }
98
+
99
+ interface ErrorCaptureRuntime {
100
+ installed: boolean;
101
+ config: Required<
102
+ Pick<
103
+ InstallErrorCaptureOptions,
104
+ | "captureGlobalErrors"
105
+ | "captureUnhandledRejections"
106
+ | "maxBreadcrumbs"
107
+ | "dedupeWindowMs"
108
+ >
109
+ > &
110
+ Omit<
111
+ InstallErrorCaptureOptions,
112
+ | "captureGlobalErrors"
113
+ | "captureUnhandledRejections"
114
+ | "maxBreadcrumbs"
115
+ | "dedupeWindowMs"
116
+ >;
117
+ breadcrumbs: ExceptionBreadcrumb[];
118
+ recentSignatures: Map<string, number>;
119
+ removeHandlers: (() => void) | null;
120
+ navigationInstalled: boolean;
121
+ }
122
+
123
+ const MAX_MESSAGE_LENGTH = 1000;
124
+ const MAX_STACK_LENGTH = 8000;
125
+ const MAX_TAGS = 30;
126
+ const MAX_EXTRA_KEYS = 50;
127
+ const MAX_EXTRA_DEPTH = 4;
128
+ const MAX_EXTRA_OBJECT_KEYS = 20;
129
+ const MAX_EXTRA_ARRAY_ITEMS = 20;
130
+ const MAX_EXTRA_STRING_LENGTH = 2000;
131
+
132
+ const ERROR_CAPTURE_STATE_KEY = Symbol.for("agent-native.client.errorCapture");
133
+
134
+ // Reuse the same credential-looking redaction the replay capture uses so a
135
+ // stack/message that echoes a token never leaves the browser in the clear.
136
+ const SECRET_KEY_FRAGMENT =
137
+ "(?:authorization|cookie|set[-_]?cookie|token|secret|password|passwd|pwd|api[-_]?key|apikey|session|credential)";
138
+ const BEARER_RE = /\b(bearer|basic)\s+[a-z0-9._~+/-]+=*/gi;
139
+ const UNQUOTED_SECRET_RE = new RegExp(
140
+ `(["']?)([A-Za-z0-9_$.-]*${SECRET_KEY_FRAGMENT}[A-Za-z0-9_$.-]*)\\1(\\s*[:=]\\s*)([^"',\\s;}\\]]+)`,
141
+ "gi",
142
+ );
143
+ const SECRET_KEY_RE = new RegExp(SECRET_KEY_FRAGMENT, "i");
144
+
145
+ function redactSecrets(value: string): string {
146
+ return value
147
+ .replace(BEARER_RE, "$1 <redacted>")
148
+ .replace(UNQUOTED_SECRET_RE, "$1$2$1$3<redacted>");
149
+ }
150
+
151
+ function getRuntime(): ErrorCaptureRuntime {
152
+ const g = globalThis as typeof globalThis & {
153
+ [ERROR_CAPTURE_STATE_KEY]?: ErrorCaptureRuntime;
154
+ };
155
+ if (!g[ERROR_CAPTURE_STATE_KEY]) {
156
+ g[ERROR_CAPTURE_STATE_KEY] = {
157
+ installed: false,
158
+ config: {
159
+ send: () => {},
160
+ captureGlobalErrors: true,
161
+ captureUnhandledRejections: true,
162
+ maxBreadcrumbs: 20,
163
+ dedupeWindowMs: 3000,
164
+ },
165
+ breadcrumbs: [],
166
+ recentSignatures: new Map(),
167
+ removeHandlers: null,
168
+ navigationInstalled: false,
169
+ };
170
+ }
171
+ return g[ERROR_CAPTURE_STATE_KEY]!;
172
+ }
173
+
174
+ function nowIso(): string {
175
+ return new Date().toISOString();
176
+ }
177
+
178
+ function truncate(value: string, max: number): string {
179
+ return value.length > max ? value.slice(0, max) : value;
180
+ }
181
+
182
+ function currentUrl(): string | undefined {
183
+ try {
184
+ return scrubUrl(window.location.href);
185
+ } catch {
186
+ return undefined;
187
+ }
188
+ }
189
+
190
+ /** Normalize any thrown value into a stable `{ type, message, stack }`. */
191
+ export function normalizeCapturedError(error: unknown): {
192
+ type: string;
193
+ message: string;
194
+ stack?: string;
195
+ } {
196
+ if (error instanceof Error) {
197
+ return {
198
+ type: error.name || "Error",
199
+ message: error.message || String(error),
200
+ stack: typeof error.stack === "string" ? error.stack : undefined,
201
+ };
202
+ }
203
+ if (typeof error === "string") {
204
+ return { type: "Error", message: error };
205
+ }
206
+ if (error && typeof error === "object") {
207
+ const record = error as Record<string, unknown>;
208
+ const name = typeof record.name === "string" ? record.name : undefined;
209
+ const message =
210
+ typeof record.message === "string" ? record.message : undefined;
211
+ const stack = typeof record.stack === "string" ? record.stack : undefined;
212
+ if (name || message || stack) {
213
+ return {
214
+ type: name || "Error",
215
+ message: message || safeStringify(error),
216
+ stack,
217
+ };
218
+ }
219
+ return { type: "Error", message: safeStringify(error) };
220
+ }
221
+ return { type: "Error", message: String(error) };
222
+ }
223
+
224
+ function safeStringify(value: unknown): string {
225
+ try {
226
+ return JSON.stringify(value) ?? String(value);
227
+ } catch {
228
+ return String(value);
229
+ }
230
+ }
231
+
232
+ function coerceTags(
233
+ tags: CaptureExceptionContext["tags"],
234
+ ): Record<string, string> | undefined {
235
+ if (!tags) return undefined;
236
+ const out: Record<string, string> = {};
237
+ let count = 0;
238
+ for (const [key, value] of Object.entries(tags)) {
239
+ if (count >= MAX_TAGS) break;
240
+ if (value === undefined || value === null) continue;
241
+ out[key] = truncate(redactSecrets(String(value)), 200);
242
+ count += 1;
243
+ }
244
+ return Object.keys(out).length ? out : undefined;
245
+ }
246
+
247
+ function coerceExtra(
248
+ extra: CaptureExceptionContext["extra"],
249
+ ): Record<string, unknown> | undefined {
250
+ if (!extra || typeof extra !== "object") return undefined;
251
+ const out: Record<string, unknown> = {};
252
+ let count = 0;
253
+ for (const [key, value] of Object.entries(extra)) {
254
+ if (count >= MAX_EXTRA_KEYS) break;
255
+ const safeKey = truncate(redactSecrets(key), 100);
256
+ out[safeKey] = SECRET_KEY_RE.test(safeKey)
257
+ ? "<redacted>"
258
+ : coerceExtraValue(value, MAX_EXTRA_DEPTH);
259
+ count += 1;
260
+ }
261
+ return Object.keys(out).length ? out : undefined;
262
+ }
263
+
264
+ function coerceExtraValue(value: unknown, depth: number): unknown {
265
+ if (
266
+ value == null ||
267
+ typeof value === "boolean" ||
268
+ typeof value === "number"
269
+ ) {
270
+ return value;
271
+ }
272
+ if (typeof value === "string") {
273
+ return truncate(redactSecrets(value), MAX_EXTRA_STRING_LENGTH);
274
+ }
275
+ if (typeof value === "bigint") {
276
+ return truncate(redactSecrets(value.toString()), MAX_EXTRA_STRING_LENGTH);
277
+ }
278
+ if (depth <= 0) {
279
+ return truncate(
280
+ redactSecrets(safeStringify(value)),
281
+ MAX_EXTRA_STRING_LENGTH,
282
+ );
283
+ }
284
+ if (Array.isArray(value)) {
285
+ return value
286
+ .slice(0, MAX_EXTRA_ARRAY_ITEMS)
287
+ .map((item) => coerceExtraValue(item, depth - 1));
288
+ }
289
+ if (typeof value === "object") {
290
+ const out: Record<string, unknown> = {};
291
+ let count = 0;
292
+ for (const [rawKey, child] of Object.entries(value)) {
293
+ if (count >= MAX_EXTRA_OBJECT_KEYS) break;
294
+ const key = truncate(redactSecrets(rawKey), 100);
295
+ out[key] = SECRET_KEY_RE.test(key)
296
+ ? "<redacted>"
297
+ : coerceExtraValue(child, depth - 1);
298
+ count += 1;
299
+ }
300
+ return out;
301
+ }
302
+ return truncate(redactSecrets(String(value)), MAX_EXTRA_STRING_LENGTH);
303
+ }
304
+
305
+ function firstStackLine(stack: string | undefined): string {
306
+ if (!stack) return "";
307
+ const lines = stack.split("\n").map((line) => line.trim());
308
+ return (
309
+ lines.find((line) => line.startsWith("at ") || /:\d+:\d+/.test(line)) ??
310
+ lines[1] ??
311
+ ""
312
+ );
313
+ }
314
+
315
+ /** Cheap client-side signature used only for local dedupe. */
316
+ function signatureOf(type: string, message: string, stack?: string): string {
317
+ return `${type}|${message}|${firstStackLine(stack)}`;
318
+ }
319
+
320
+ function shouldDedupe(
321
+ runtime: ErrorCaptureRuntime,
322
+ signature: string,
323
+ ): boolean {
324
+ const now = Date.now();
325
+ const windowMs = runtime.config.dedupeWindowMs;
326
+ // Opportunistic cleanup so the map can't grow without bound.
327
+ if (runtime.recentSignatures.size > 200) {
328
+ for (const [key, ts] of runtime.recentSignatures) {
329
+ if (now - ts > windowMs) runtime.recentSignatures.delete(key);
330
+ }
331
+ }
332
+ const last = runtime.recentSignatures.get(signature);
333
+ runtime.recentSignatures.set(signature, now);
334
+ return last !== undefined && now - last < windowMs;
335
+ }
336
+
337
+ /** Append a privacy-safe breadcrumb to the bounded ring buffer. */
338
+ export function addErrorBreadcrumb(breadcrumb: {
339
+ category: string;
340
+ message: string;
341
+ level?: ExceptionLevel;
342
+ }): void {
343
+ try {
344
+ const runtime = getRuntime();
345
+ runtime.breadcrumbs.push({
346
+ timestamp: nowIso(),
347
+ category: truncate(breadcrumb.category, 60),
348
+ message: truncate(redactSecrets(breadcrumb.message), 300),
349
+ ...(breadcrumb.level ? { level: breadcrumb.level } : {}),
350
+ });
351
+ const max = runtime.config.maxBreadcrumbs;
352
+ if (runtime.breadcrumbs.length > max) {
353
+ runtime.breadcrumbs.splice(0, runtime.breadcrumbs.length - max);
354
+ }
355
+ } catch {
356
+ // breadcrumbs are best-effort
357
+ }
358
+ }
359
+
360
+ function snapshotBreadcrumbs(
361
+ runtime: ErrorCaptureRuntime,
362
+ ): ExceptionBreadcrumb[] {
363
+ return runtime.breadcrumbs.slice(-runtime.config.maxBreadcrumbs);
364
+ }
365
+
366
+ function installNavigationBreadcrumbs(runtime: ErrorCaptureRuntime): void {
367
+ if (runtime.navigationInstalled || typeof window === "undefined") return;
368
+ runtime.navigationInstalled = true;
369
+ const record = (navType: string) => {
370
+ try {
371
+ addErrorBreadcrumb({
372
+ category: "navigation",
373
+ message: `${navType} ${scrubUrl(window.location.href) ?? window.location.pathname}`,
374
+ });
375
+ } catch {
376
+ // ignore
377
+ }
378
+ };
379
+ try {
380
+ const originalPush = window.history.pushState;
381
+ const originalReplace = window.history.replaceState;
382
+ window.history.pushState = function pushState(...args) {
383
+ const result = originalPush.apply(this, args);
384
+ record("navigate");
385
+ return result;
386
+ };
387
+ window.history.replaceState = function replaceState(...args) {
388
+ const result = originalReplace.apply(this, args);
389
+ record("replace");
390
+ return result;
391
+ };
392
+ window.addEventListener("popstate", () => record("popstate"));
393
+ // Seed the trail with the initial location.
394
+ record("load");
395
+ } catch {
396
+ // navigation breadcrumbs are best-effort
397
+ }
398
+ }
399
+
400
+ function buildEvent(
401
+ runtime: ErrorCaptureRuntime,
402
+ normalized: { type: string; message: string; stack?: string },
403
+ options: {
404
+ handled: boolean;
405
+ level: ExceptionLevel;
406
+ tags?: Record<string, string>;
407
+ extra?: Record<string, unknown>;
408
+ },
409
+ ): CapturedExceptionEvent {
410
+ const context = runtime.config.getSessionContext?.() ?? {};
411
+ const stack = normalized.stack
412
+ ? truncate(redactSecrets(normalized.stack), MAX_STACK_LENGTH)
413
+ : undefined;
414
+ return {
415
+ type: truncate(normalized.type || "Error", 200),
416
+ message: truncate(
417
+ redactSecrets(normalized.message || ""),
418
+ MAX_MESSAGE_LENGTH,
419
+ ),
420
+ ...(stack ? { stack } : {}),
421
+ handled: options.handled,
422
+ level: options.level,
423
+ occurredAt: nowIso(),
424
+ ...(currentUrl() ? { url: currentUrl() } : {}),
425
+ ...(runtime.config.release ? { release: runtime.config.release } : {}),
426
+ ...(runtime.config.environment
427
+ ? { environment: runtime.config.environment }
428
+ : {}),
429
+ ...(context.sessionId ? { sessionId: context.sessionId } : {}),
430
+ ...(context.replayId ? { sessionReplayId: context.replayId } : {}),
431
+ ...(context.anonymousId ? { anonymousId: context.anonymousId } : {}),
432
+ breadcrumbs: snapshotBreadcrumbs(runtime),
433
+ ...(options.tags ? { tags: options.tags } : {}),
434
+ ...(options.extra ? { extra: options.extra } : {}),
435
+ };
436
+ }
437
+
438
+ function dispatch(
439
+ runtime: ErrorCaptureRuntime,
440
+ event: CapturedExceptionEvent,
441
+ emitToReplay: boolean,
442
+ ): void {
443
+ const signature = signatureOf(event.type, event.message, event.stack);
444
+ if (shouldDedupe(runtime, signature)) return;
445
+ try {
446
+ runtime.config.send(event);
447
+ } catch {
448
+ // transport must never throw into the host app
449
+ }
450
+ if (emitToReplay) {
451
+ try {
452
+ runtime.config.emitReplayEvent?.(event);
453
+ } catch {
454
+ // replay timeline emission is best-effort
455
+ }
456
+ }
457
+ // Record the exception itself as a breadcrumb so a following error carries
458
+ // the prior failure in its trail.
459
+ addErrorBreadcrumb({
460
+ category: "exception",
461
+ message: `${event.type}: ${event.message}`,
462
+ level: event.level,
463
+ });
464
+ }
465
+
466
+ /**
467
+ * Capture a handled exception. Mirrors Sentry's `captureException(err, ctx)`.
468
+ * Safe to call before `configureTracking` has run — it simply no-ops if no
469
+ * transport is installed yet.
470
+ */
471
+ export function captureException(
472
+ error: unknown,
473
+ context: CaptureExceptionContext = {},
474
+ ): void {
475
+ try {
476
+ const runtime = getRuntime();
477
+ const normalized = normalizeCapturedError(error);
478
+ const event = buildEvent(runtime, normalized, {
479
+ handled: true,
480
+ level: context.level ?? "error",
481
+ tags: coerceTags(context.tags),
482
+ extra: coerceExtra(context.extra),
483
+ });
484
+ dispatch(runtime, event, true);
485
+ } catch {
486
+ // never throw from capture
487
+ }
488
+ }
489
+
490
+ /**
491
+ * Capture a message string as an exception-like event. Mirrors Sentry's
492
+ * `captureMessage(message, level?)`.
493
+ */
494
+ export function captureMessage(
495
+ message: string,
496
+ level: ExceptionLevel = "info",
497
+ ): void {
498
+ try {
499
+ const runtime = getRuntime();
500
+ const event = buildEvent(
501
+ runtime,
502
+ { type: "Message", message: String(message ?? "") },
503
+ { handled: true, level },
504
+ );
505
+ dispatch(runtime, event, true);
506
+ } catch {
507
+ // never throw from capture
508
+ }
509
+ }
510
+
511
+ /**
512
+ * Install auto-capture + wire the transport. Idempotent: re-invoking updates
513
+ * the config (and (re)installs global handlers) without duplicating listeners.
514
+ * Returns a disposer that removes the global handlers.
515
+ */
516
+ export function installErrorCapture(
517
+ options: InstallErrorCaptureOptions,
518
+ ): () => void {
519
+ const runtime = getRuntime();
520
+ runtime.config = {
521
+ ...runtime.config,
522
+ ...options,
523
+ captureGlobalErrors: options.captureGlobalErrors ?? true,
524
+ captureUnhandledRejections: options.captureUnhandledRejections ?? true,
525
+ maxBreadcrumbs: options.maxBreadcrumbs ?? runtime.config.maxBreadcrumbs,
526
+ dedupeWindowMs: options.dedupeWindowMs ?? runtime.config.dedupeWindowMs,
527
+ };
528
+
529
+ if (typeof window === "undefined") return () => {};
530
+
531
+ installNavigationBreadcrumbs(runtime);
532
+
533
+ // Tear down any previously-installed handlers before reinstalling so a second
534
+ // configureTracking call doesn't double-report.
535
+ runtime.removeHandlers?.();
536
+ runtime.removeHandlers = null;
537
+
538
+ const removers: Array<() => void> = [];
539
+
540
+ if (runtime.config.captureGlobalErrors) {
541
+ const onError = (event: ErrorEvent) => {
542
+ try {
543
+ const error = event?.error;
544
+ const normalized = error
545
+ ? normalizeCapturedError(error)
546
+ : {
547
+ type: "Error",
548
+ message: String(event?.message ?? "Uncaught error"),
549
+ };
550
+ // Global errors are already logged by the session replay recorder, so
551
+ // don't re-emit them onto the replay timeline (avoid double-counting).
552
+ dispatch(
553
+ runtime,
554
+ buildEvent(runtime, normalized, {
555
+ handled: false,
556
+ level: "error",
557
+ }),
558
+ false,
559
+ );
560
+ } catch {
561
+ // never throw from the listener
562
+ }
563
+ };
564
+ window.addEventListener("error", onError as EventListener);
565
+ removers.push(() =>
566
+ window.removeEventListener("error", onError as EventListener),
567
+ );
568
+ }
569
+
570
+ if (runtime.config.captureUnhandledRejections) {
571
+ const onRejection = (event: PromiseRejectionEvent) => {
572
+ try {
573
+ const reason = event?.reason;
574
+ const normalized = normalizeCapturedError(reason);
575
+ if (!normalized.type || normalized.type === "Error") {
576
+ normalized.type = "UnhandledRejection";
577
+ }
578
+ dispatch(
579
+ runtime,
580
+ buildEvent(runtime, normalized, {
581
+ handled: false,
582
+ level: "error",
583
+ }),
584
+ false,
585
+ );
586
+ } catch {
587
+ // never throw from the listener
588
+ }
589
+ };
590
+ window.addEventListener("unhandledrejection", onRejection as EventListener);
591
+ removers.push(() =>
592
+ window.removeEventListener(
593
+ "unhandledrejection",
594
+ onRejection as EventListener,
595
+ ),
596
+ );
597
+ }
598
+
599
+ runtime.installed = true;
600
+ runtime.removeHandlers = () => {
601
+ for (const remove of removers) {
602
+ try {
603
+ remove();
604
+ } catch {
605
+ // best-effort teardown
606
+ }
607
+ }
608
+ runtime.removeHandlers = null;
609
+ runtime.installed = false;
610
+ };
611
+ return runtime.removeHandlers;
612
+ }
613
+
614
+ export function isErrorCaptureInstalled(): boolean {
615
+ return getRuntime().installed;
616
+ }
@@ -652,6 +652,7 @@ export {
652
652
  type OpenBuilderConnectPopupOptions,
653
653
  type SecretsSectionProps,
654
654
  type SettingsPanelProps,
655
+ type SettingsSearchEntry,
655
656
  type SettingsTabItem,
656
657
  type SettingsTabsPageProps,
657
658
  } from "./settings/index.js";
@@ -733,8 +734,19 @@ export {
733
734
  setSentryUser,
734
735
  captureError,
735
736
  captureClientException,
737
+ // First-party, Sentry-style error capture (auto + manual API).
738
+ AGENT_NATIVE_EXCEPTION_EVENT_NAME,
739
+ addErrorBreadcrumb,
740
+ captureException,
741
+ captureMessage,
742
+ isErrorCaptureInstalled,
743
+ type CaptureExceptionContext,
744
+ type CapturedExceptionEvent,
736
745
  type ClientCaptureContext,
737
746
  type ConfigureTrackingOptions,
747
+ type ErrorCaptureConfigOptions,
748
+ type ExceptionBreadcrumb,
749
+ type ExceptionLevel,
738
750
  type FirstTouchAttribution,
739
751
  type SessionReplayOptions,
740
752
  type SessionReplayStartResult,