@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,172 @@
1
+ # Error capture
2
+
3
+ First-party, Sentry-style exception tracking built into the analytics product.
4
+ The browser SDK automatically captures uncaught exceptions and unhandled
5
+ promise rejections, exposes a manual `captureException` / `captureMessage` API,
6
+ and links every error to the **session replay** it happened in. Captured errors
7
+ are grouped into **issues** by fingerprint and triaged under **Monitoring →
8
+ Errors**.
9
+
10
+ ## How it works
11
+
12
+ ```
13
+ Browser SDK ──$exception──▶ /api/analytics/track ──▶ error_issues + error_events
14
+ (auto + manual capture) (first-party ingest fork) (grouped issues + occurrences)
15
+ │ │
16
+ └── session replay id (localStorage) ───────────────────▶ linked to /sessions/<id>
17
+ ```
18
+
19
+ - **Capture** happens in the analytics client SDK
20
+ (`@agent-native/core/client`), installed by `configureTracking`.
21
+ - **Transport** reuses the existing first-party analytics ingest: exceptions are
22
+ sent as a dedicated `$exception` event using the same public-key auth and
23
+ `sendBeacon`/`keepalive` transport as pageviews. No extra endpoint, CORS, or
24
+ key to configure.
25
+ - **Server** forks `$exception` events out of the analytics batch, parses the
26
+ stack, computes a stable fingerprint, upserts the grouped issue, appends the
27
+ occurrence, and links the session replay. The event is still recorded in
28
+ `analytics_events`, so existing alerting keeps working.
29
+
30
+ ## Enabling capture
31
+
32
+ Templates already call `configureTracking`. Error capture **auto-enables**
33
+ whenever a first-party analytics public key is configured (the same trigger as
34
+ pageview tracking and session replay). To be explicit or to tune it:
35
+
36
+ ```ts
37
+ import { configureTracking } from "@agent-native/core/client";
38
+
39
+ configureTracking({
40
+ key: "anpk_...", // first-party analytics public key
41
+ endpoint: "https://analytics.example.com/api/analytics/track",
42
+ errorCapture: true, // or an options object; pass `false` to disable
43
+ });
44
+ ```
45
+
46
+ Options (`errorCapture` object form):
47
+
48
+ | Option | Default | Description |
49
+ | ---------------------------- | ----------- | --------------------------------------------- |
50
+ | `release` | `undefined` | Build/release id attached to every exception. |
51
+ | `environment` | Vite `MODE` | Deployment environment (e.g. `production`). |
52
+ | `captureGlobalErrors` | `true` | Auto-capture `window.onerror`. |
53
+ | `captureUnhandledRejections` | `true` | Auto-capture `unhandledrejection`. |
54
+ | `maxBreadcrumbs` | `20` | Breadcrumb ring-buffer size. |
55
+
56
+ > Exceptions are only transmitted from non-local hostnames (same rule as the
57
+ > rest of first-party analytics). In local dev the handlers still install, but
58
+ > nothing is sent — use the **Send test error** button or the
59
+ > `capture-test-error` action to exercise the pipeline end to end.
60
+
61
+ ## Automatic capture
62
+
63
+ Once installed, the SDK listens for:
64
+
65
+ - **`window.onerror`** — uncaught synchronous and asynchronous errors.
66
+ - **`unhandledrejection`** — promise rejections with no `.catch`.
67
+
68
+ Each is normalized into `{ type, message, stack, url, handled, level, … }`,
69
+ redacted, deduped (identical signatures within a short window are dropped), and
70
+ sent. The session replay recorder already logs these to the replay timeline, so
71
+ auto-captured errors are **not** re-emitted onto the timeline to avoid
72
+ double-counting.
73
+
74
+ ## Manual API (Sentry-style)
75
+
76
+ ```ts
77
+ import { captureException, captureMessage } from "@agent-native/core/client";
78
+
79
+ try {
80
+ doRiskyThing();
81
+ } catch (err) {
82
+ captureException(err, {
83
+ level: "error",
84
+ tags: { area: "checkout", plan: "pro" },
85
+ extra: { cartId, itemCount },
86
+ });
87
+ }
88
+
89
+ captureMessage("Payment webhook retried", "warning");
90
+ ```
91
+
92
+ - `captureException(error, context?)` — `context` accepts `tags` (low-cardinality
93
+ strings), `extra` (structured detail), and `level`
94
+ (`fatal | error | warning | info | debug`, default `error`).
95
+ - `captureMessage(message, level?)` — capture a string as an exception-like
96
+ event (default level `info`).
97
+ - `addErrorBreadcrumb({ category, message, level? })` — add a privacy-safe
98
+ breadcrumb to the bounded trail attached to the next captured error.
99
+
100
+ Manual captures **are** surfaced on the active session replay timeline as a
101
+ custom event, so they show up when you watch the replay.
102
+
103
+ Both functions are safe to call before `configureTracking` runs (they no-op
104
+ until transport is installed) and never throw back into your app.
105
+
106
+ ## Session replay linkage
107
+
108
+ The SDK reads the current session replay id from `localStorage`
109
+ (`agent-native.session_replay_id`) and attaches it to each exception. At ingest
110
+ the server resolves it to the real recording (`sr_...`) and stores it on the
111
+ occurrence and the issue (`lastSessionRecordingId`). In the Errors UI, each
112
+ issue and occurrence with a linked replay shows a **Watch session replay** link
113
+ straight to `/sessions/<recordingId>`, so you can watch what the user did right
114
+ before the error.
115
+
116
+ The link goes both ways. When you watch a recording and open its devtools
117
+ **Console** panel, any captured error line (uncaught exceptions, unhandled
118
+ rejections, manual `captureException`) gets a **View issue** link straight to
119
+ its grouped issue detail (`/monitoring?view=errors&issue=<id>`) — how many users
120
+ hit it, the stack trace, and recent occurrences. Resolution is exact, not
121
+ heuristic: the `match-error-issues` action recomputes each console line's
122
+ fingerprint with the same helpers used at ingest and looks it up under access
123
+ scope, so a link only appears when the error was actually captured as an issue.
124
+
125
+ ## Privacy & redaction
126
+
127
+ - Messages and stacks are scrubbed for credential-looking values
128
+ (`Authorization`, `Cookie`, `token`, `apiKey`, bearer/basic tokens, …) before
129
+ they leave the browser, reusing the same redaction as replay capture.
130
+ - URLs are scrubbed of query strings/tokens.
131
+ - Breadcrumbs are bounded (ring buffer) and only record navigation + explicit
132
+ messages — no DOM values or input contents.
133
+ - Payloads are size-bounded (message, stack, tags, extra, breadcrumbs).
134
+
135
+ ## Data model
136
+
137
+ Two additive, owner-scoped tables (`server/db/schema-errors.ts`):
138
+
139
+ - **`error_issues`** — one row per fingerprint per owner scope. `ownableColumns()`
140
+ - `error_issue_shares`, so an org-scoped analytics key surfaces issues to the
141
+ whole org via `accessFilter` (mirrors `session_recordings`). Tracks status
142
+ (`unresolved | resolved | ignored`), counts, first/last seen, users affected,
143
+ culprit/title, and the last linked recording.
144
+ - **`error_events`** — individual occurrences (owner-scoped like
145
+ `analytics_events`), pruned to a bounded retention per issue so occurrences
146
+ can't grow unbounded. Stores normalized stack frames, breadcrumbs, tags/extra,
147
+ and the resolved session recording.
148
+
149
+ Grouping keys off error type + top in-app stack frame (function + normalized
150
+ file, ignoring line/column so small edits don't split a group), falling back to
151
+ a normalized message when there is no usable stack. A resolved issue is
152
+ automatically **reopened** when it recurs; **ignored** issues stay muted.
153
+
154
+ ## How the agent triages issues
155
+
156
+ The agent uses the same owner-scoped actions the UI does:
157
+
158
+ - **`list-error-issues`** — list grouped issues, filter by status, search, sort
159
+ by last seen / event count / first seen.
160
+ - **`get-error-issue`** — one issue with recent occurrences (parsed stack
161
+ frames, breadcrumbs, tags/extra) and links to the session replays where it
162
+ happened.
163
+ - **`resolve-error-issue`** — set status (`unresolved` / `resolved` / `ignored`)
164
+ and optionally (re)assign a triage owner.
165
+ - **`capture-test-error`** — generate a sample captured error to verify the
166
+ pipeline end to end.
167
+ - **`match-error-issues`** — resolve a batch of session console error lines
168
+ (message/stack/source) to their captured issue ids, so a session recording can
169
+ deep-link to issue detail. Read-only; fingerprints match ingest exactly.
170
+
171
+ New issues also raise a best-effort inbox notification (via
172
+ `notifyWithDelivery`) so a fresh error surfaces without opening the dashboard.
@@ -0,0 +1,150 @@
1
+ # Uptime monitoring
2
+
3
+ Uptime monitoring lets you create **monitors** — synthetic HTTP checks that ping
4
+ a URL on a schedule and alert you (or others) when something is wrong:
5
+
6
+ - the URL is **unreachable** or **times out**,
7
+ - it returns a **non-expected status** (e.g. a `5xx` when you expect `2xx`),
8
+ - it is **too slow** (a latency budget you set), or
9
+ - its response body is **missing expected text** or **contains forbidden text**.
10
+
11
+ It reuses the same notification pipeline as the analytics alert rules, so alerts
12
+ land in the in-app inbox and can also fan out to email, Slack, and webhooks.
13
+
14
+ The feature lives under **Monitoring → Uptime** (`/monitoring?view=uptime`). A
15
+ selected monitor is reflected in the URL as `?view=uptime&monitor=<id>` so links
16
+ are shareable and the agent can deep-link a monitor.
17
+
18
+ ## How a check works
19
+
20
+ Each check runs on the server (`server/lib/uptime-monitors.ts`):
21
+
22
+ 1. Fetch the monitor's `url` with the configured `method`, headers, and body,
23
+ through an SSRF-safe path, with an `AbortController` timeout.
24
+ 2. Measure latency and read up to **512 KB** of the response body (skipped for
25
+ `HEAD`).
26
+ 3. Evaluate the **status matcher** and every **assertion**.
27
+ 4. Classify the result:
28
+ - `up` — status matches and all assertions pass.
29
+ - `degraded` — status matches but only a `max_latency_ms` assertion fails
30
+ (the endpoint responded, just too slowly). Alerts at `warning` severity.
31
+ - `down` — the status does not match, a content/header assertion fails, or
32
+ the request errored/timed out. Alerts at the monitor's configured severity.
33
+ - `error` — a configuration/SSRF problem prevented the check from running.
34
+
35
+ ### Status matcher
36
+
37
+ `expectedStatus` accepts one of three shapes (stored as JSON):
38
+
39
+ ```jsonc
40
+ { "mode": "class", "classes": ["2xx", "3xx"] } // any 2xx or 3xx
41
+ { "mode": "list", "codes": [200, 204] } // exact codes
42
+ { "mode": "range", "min": 200, "max": 299 } // inclusive range
43
+ ```
44
+
45
+ ### Assertions
46
+
47
+ `assertions` is a JSON array. All assertions must pass for a check to be `up`.
48
+
49
+ | type | meaning | fields |
50
+ | ----------------- | ------------------------------------------------ | ----------------- |
51
+ | `body_contains` | response body must contain the text | `value` |
52
+ | `body_absent` | response body must NOT contain the text | `value` |
53
+ | `header_contains` | a response header must contain the text | `header`, `value` |
54
+ | `header_equals` | a response header must equal the text | `header`, `value` |
55
+ | `max_latency_ms` | response must arrive within N ms (else degraded) | `value` (number) |
56
+
57
+ ## Alerting and recovery
58
+
59
+ `evaluateAndNotifyMonitor` manages incidents like the analytics alert engine:
60
+
61
+ - On a transition **into failure**, it opens a `monitor_incidents` row (one per
62
+ continuous failure streak) and calls `notifyWithDelivery` with a clear title
63
+ and body plus metadata
64
+ `{ kind: "uptime_monitor", monitorId, url, statusCode, latencyMs, failedAssertions }`.
65
+ The `inbox` channel is always included; `email`/`slack`/`webhook` are added
66
+ when configured, and email uses the monitor's `emailRecipients`.
67
+ - While an incident is open it will not re-alert. After an incident resolves,
68
+ `cooldownMinutes` suppresses a fresh "down" alert for that window to prevent
69
+ flapping.
70
+ - On **recovery**, it resolves the open incident and sends an informational
71
+ "recovered" notification (with downtime duration).
72
+
73
+ A `lastStatus === "running"` claim guard (with a staleness timeout) ensures that
74
+ concurrent sweeps never double-run the same monitor.
75
+
76
+ ## Security (SSRF)
77
+
78
+ Because monitors fetch user-supplied URLs from the server, `runMonitorCheck`
79
+ guards against SSRF:
80
+
81
+ - Only `http:` / `https:` URLs are allowed.
82
+ - Requests to loopback, link-local, private RFC1918 ranges, and cloud metadata
83
+ IPs are blocked — both by a literal pre-flight check and by DNS resolution of
84
+ the resolved host (including across redirects). Blocked hosts classify as
85
+ `error`, never a successful check.
86
+ - Redirects are followed manually (max 5 hops) and each hop is re-validated; when
87
+ `followRedirects` is off, a `3xx` is returned as-is.
88
+ - The response body read is capped at 512 KB before text assertions run.
89
+
90
+ To monitor internal/private hosts in development or a self-hosted deployment,
91
+ set `UPTIME_MONITOR_ALLOW_PRIVATE_HOSTS=1` (off by default).
92
+
93
+ ## Background job
94
+
95
+ The sweep is registered by `server/plugins/uptime-monitor-jobs.ts` and runs
96
+ `runDueMonitorsOnce()` (`server/jobs/uptime-monitors.ts`), which selects enabled
97
+ monitors whose interval has elapsed, checks them, records results, opens/resolves
98
+ incidents, and prunes old check results.
99
+
100
+ Environment flags (mirrors the analytics alert job):
101
+
102
+ | flag | effect |
103
+ | -------------------------------------- | ------------------------------------------------------------------- |
104
+ | `UPTIME_MONITOR_JOBS` | `1` enables the in-process cron; `0` disables it. |
105
+ | `RUN_BACKGROUND_JOBS` | fallback flag when `UPTIME_MONITOR_JOBS` is unset. |
106
+ | (production) | on by default unless a flag is `0` or a platform scheduler owns it. |
107
+ | `UPTIME_MONITOR_INTERVAL_MS` | wake interval for the sweep (default 30s, min 10s). |
108
+ | `UPTIME_MONITOR_SWEEP_LIMIT` | max monitors processed per sweep (default 100). |
109
+ | `UPTIME_MONITOR_RESULT_RETENTION_DAYS` | how long check results are kept (default 30). |
110
+ | `UPTIME_MONITOR_ALLOW_PRIVATE_HOSTS` | allow probing private/internal hosts. |
111
+
112
+ The monitor tables (`monitors`, `monitor_check_results`, `monitor_incidents`)
113
+ are created by the app migration list in `server/plugins/db.ts`, which runs at
114
+ boot regardless of whether the cron is enabled — so the actions and UI always
115
+ have their schema.
116
+
117
+ ## Managing monitors from the agent
118
+
119
+ Every operation is an owner-scoped action, so the agent can create and triage
120
+ monitors from chat exactly like the UI:
121
+
122
+ | action | method | what it does |
123
+ | ------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
124
+ | `save-monitor` | POST | create or update a monitor (name, url, method, interval, timeout, expected status, assertions, redirects, severity, channels, email recipients, cooldown, enabled). |
125
+ | `list-monitors` | GET | list monitors with latest status, latency, and 24h/7d uptime %. |
126
+ | `get-monitor` | GET | one monitor plus its recent check results and incidents. |
127
+ | `delete-monitor` | POST | delete a monitor and its results + incidents. |
128
+ | `run-monitor-check` | POST | run one check now, record it, and open/resolve incidents. |
129
+
130
+ Example prompts:
131
+
132
+ - "Monitor https://example.com every 5 minutes and email me if it returns a 5xx
133
+ or the page stops containing 'Sign in'."
134
+ - "Which monitors are down right now?" (→ `list-monitors`)
135
+ - "Run a check on the marketing site now." (→ `run-monitor-check`)
136
+
137
+ ## Data model
138
+
139
+ All three tables carry `ownableColumns()` (`owner_email` / `org_id` /
140
+ `visibility`) and every read/write is scoped by owner + org.
141
+
142
+ - **`monitors`** — configuration plus mutable status fields (`last_status`,
143
+ `last_checked_at`, `last_success_at`, `last_error`, `last_latency_ms`,
144
+ `last_status_code`, `consecutive_failures`).
145
+ - **`monitor_check_results`** — one row per probe (`ok`, `status`, `status_code`,
146
+ `latency_ms`, `error`, `failed_assertions`), indexed on
147
+ `(monitor_id, checked_at)`; pruned by the sweep so it stays bounded.
148
+ - **`monitor_incidents`** — one row per failure streak (`started_at`,
149
+ `resolved_at` null = ongoing, `cause`, `severity`, `notification_id`,
150
+ `checks_failed`).
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Error capture schema — OWNED BY THE ERROR CAPTURE FEATURE.
3
+ *
4
+ * Everything exported here is re-exported from ./schema.ts via `export *`, so
5
+ * these tables join the app's Drizzle schema namespace and are reachable as
6
+ * `schema.<table>` throughout the server. Keep all schema changes additive
7
+ * (never drop/rename/retype existing columns) per the storing-data rules.
8
+ *
9
+ * Two tables, Sentry-style:
10
+ * - `error_issues` — the grouped issue (one row per fingerprint per owner
11
+ * scope). Ownable + shareable so an org-scoped analytics key surfaces its
12
+ * issues to the whole org via `accessFilter`, mirroring session_recordings.
13
+ * - `error_events` — individual occurrences. High-volume, owner-scoped like
14
+ * `analytics_events` (plain owner columns, not `ownableColumns()`), always
15
+ * read behind an issue the caller already has access to, and pruned to a
16
+ * bounded retention per issue so occurrences can't grow unbounded.
17
+ */
18
+ import {
19
+ createSharesTable,
20
+ index,
21
+ integer,
22
+ now,
23
+ ownableColumns,
24
+ table,
25
+ text,
26
+ uniqueIndex,
27
+ } from "@agent-native/core/db/schema";
28
+
29
+ /**
30
+ * Grouped error issues. A stable `fingerprint` (error type + top meaningful
31
+ * stack frame, or message when there's no usable stack) collapses many
32
+ * occurrences into one triageable issue.
33
+ */
34
+ export const errorIssues = table(
35
+ "error_issues",
36
+ {
37
+ id: text("id").primaryKey(),
38
+ /** Stable grouping key; unique per owner scope. */
39
+ fingerprint: text("fingerprint").notNull(),
40
+ /** Error class/name, e.g. "TypeError" or "Error" (or "Message"). */
41
+ type: text("type").notNull().default("Error"),
42
+ /** Human-readable issue title (type + first line of the message). */
43
+ title: text("title").notNull(),
44
+ /** Best-effort culprit — the top in-app frame ("fn (file:line)"). */
45
+ culprit: text("culprit"),
46
+ level: text("level", {
47
+ enum: ["fatal", "error", "warning", "info", "debug"],
48
+ })
49
+ .notNull()
50
+ .default("error"),
51
+ status: text("status", {
52
+ enum: ["unresolved", "resolved", "ignored"],
53
+ })
54
+ .notNull()
55
+ .default("unresolved"),
56
+ firstSeenAt: text("first_seen_at").notNull(),
57
+ lastSeenAt: text("last_seen_at").notNull(),
58
+ /** Lifetime occurrence count (monotonic; not affected by retention). */
59
+ eventCount: integer("event_count").notNull().default(0),
60
+ /** Approximate distinct users, recomputed over retained occurrences. */
61
+ usersAffected: integer("users_affected").notNull().default(0),
62
+ /** id of a representative occurrence for the detail view. */
63
+ sampleEventId: text("sample_event_id"),
64
+ /** Most recent linked session_recordings.id (sr_...), if any. */
65
+ lastSessionRecordingId: text("last_session_recording_id"),
66
+ /** Optional triage owner (email). */
67
+ assignee: text("assignee"),
68
+ /** Denormalized product dimensions for filtering/display. */
69
+ app: text("app"),
70
+ template: text("template"),
71
+ createdAt: text("created_at").notNull().default(now()),
72
+ updatedAt: text("updated_at").notNull().default(now()),
73
+ ...ownableColumns(),
74
+ },
75
+ (issue) => ({
76
+ scopeFingerprintUnique: uniqueIndex(
77
+ "error_issues_scope_fingerprint_idx",
78
+ ).on(issue.ownerEmail, issue.orgId, issue.fingerprint),
79
+ scopeLastSeenIdx: index("error_issues_scope_last_seen_idx").on(
80
+ issue.ownerEmail,
81
+ issue.orgId,
82
+ issue.lastSeenAt,
83
+ ),
84
+ scopeStatusIdx: index("error_issues_scope_status_idx").on(
85
+ issue.orgId,
86
+ issue.ownerEmail,
87
+ issue.status,
88
+ issue.lastSeenAt,
89
+ ),
90
+ }),
91
+ );
92
+
93
+ export const errorIssueShares = createSharesTable("error_issue_shares");
94
+
95
+ /**
96
+ * Individual error occurrences (events). Owner-scoped like analytics_events.
97
+ * Always read behind an issue whose access the caller already resolved through
98
+ * `accessFilter`, and additionally filtered by owner scope for defense in
99
+ * depth. Pruned to a bounded retention per issue at ingest time.
100
+ */
101
+ export const errorEvents = table(
102
+ "error_events",
103
+ {
104
+ id: text("id").primaryKey(),
105
+ issueId: text("issue_id").notNull(),
106
+ fingerprint: text("fingerprint").notNull(),
107
+ type: text("type").notNull().default("Error"),
108
+ message: text("message").notNull().default(""),
109
+ culprit: text("culprit"),
110
+ level: text("level", {
111
+ enum: ["fatal", "error", "warning", "info", "debug"],
112
+ })
113
+ .notNull()
114
+ .default("error"),
115
+ /** Normalized stack frames as JSON (ParsedStackFrame[]). */
116
+ stack: text("stack").notNull().default("[]"),
117
+ /** Bounded raw stack string kept for display fidelity. */
118
+ rawStack: text("raw_stack"),
119
+ handled: integer("handled", { mode: "boolean" }).notNull().default(true),
120
+ url: text("url"),
121
+ userId: text("user_id"),
122
+ anonymousId: text("anonymous_id"),
123
+ userKey: text("user_key"),
124
+ sessionId: text("session_id"),
125
+ /** Client replay id (localStorage) reported by the SDK. */
126
+ clientRecordingId: text("client_recording_id"),
127
+ /** Resolved session_recordings.id (sr_...) when a replay exists. */
128
+ sessionRecordingId: text("session_recording_id"),
129
+ release: text("release"),
130
+ environment: text("environment"),
131
+ tags: text("tags").notNull().default("{}"),
132
+ extra: text("extra").notNull().default("{}"),
133
+ breadcrumbs: text("breadcrumbs").notNull().default("[]"),
134
+ occurredAt: text("occurred_at").notNull(),
135
+ createdAt: text("created_at").notNull().default(now()),
136
+ ownerEmail: text("owner_email").notNull().default("local@localhost"),
137
+ orgId: text("org_id"),
138
+ },
139
+ (event) => ({
140
+ issueOccurredIdx: index("error_events_issue_occurred_idx").on(
141
+ event.issueId,
142
+ event.occurredAt,
143
+ ),
144
+ scopeOccurredIdx: index("error_events_scope_occurred_idx").on(
145
+ event.ownerEmail,
146
+ event.orgId,
147
+ event.occurredAt,
148
+ ),
149
+ }),
150
+ );
@@ -0,0 +1,177 @@
1
+ /**
2
+ * Uptime monitoring schema — OWNED BY THE UPTIME MONITORING FEATURE.
3
+ *
4
+ * Everything exported here is re-exported from ./schema.ts via `export *`, so
5
+ * these tables join the app's Drizzle schema namespace and are reachable as
6
+ * `schema.<table>` throughout the server. Keep all schema changes additive
7
+ * (never drop/rename/retype existing columns) per the storing-data rules.
8
+ *
9
+ * Physical table creation + indexes are applied by the isolated migration list
10
+ * in server/plugins/uptime-monitor-jobs.ts (`uptime_monitor_migrations`), NOT
11
+ * by drizzle-kit. These Drizzle definitions must stay in lockstep with that
12
+ * DDL (snake_case column names, dialect-agnostic types).
13
+ *
14
+ * All three tables carry `ownableColumns()` (owner_email / org_id / visibility)
15
+ * and every read/write in server/lib/uptime-monitors.ts is scoped by
16
+ * owner_email + org_id, mirroring the analytics-alerts engine.
17
+ */
18
+ import {
19
+ integer,
20
+ now,
21
+ ownableColumns,
22
+ table,
23
+ text,
24
+ } from "@agent-native/core/db/schema";
25
+
26
+ /**
27
+ * A single uptime check ("monitor"). Pings `url` on `intervalSeconds` and
28
+ * evaluates the response against a status matcher + a list of assertions.
29
+ */
30
+ export const monitors = table("monitors", {
31
+ id: text("id").primaryKey(),
32
+ name: text("name").notNull(),
33
+ url: text("url").notNull(),
34
+ /** HTTP method used for the probe. */
35
+ method: text("method", {
36
+ enum: ["GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
37
+ })
38
+ .notNull()
39
+ .default("GET"),
40
+ /** Extra request headers as a JSON object (`Record<string,string>`). */
41
+ requestHeaders: text("request_headers").notNull().default("{}"),
42
+ /** Optional request body (POST/PUT/PATCH). */
43
+ requestBody: text("request_body"),
44
+ intervalSeconds: integer("interval_seconds").notNull().default(300),
45
+ timeoutMs: integer("timeout_ms").notNull().default(15000),
46
+ /**
47
+ * Status matcher as JSON. One of:
48
+ * { "mode": "class", "classes": ["2xx","3xx"] }
49
+ * { "mode": "list", "codes": [200,204] }
50
+ * { "mode": "range", "min": 200, "max": 299 }
51
+ */
52
+ expectedStatus: text("expected_status")
53
+ .notNull()
54
+ .default('{"mode":"class","classes":["2xx"]}'),
55
+ /**
56
+ * JSON array of assertions. Each entry:
57
+ * { "type": "body_contains" | "body_absent" | "header_contains" |
58
+ * "header_equals" | "max_latency_ms",
59
+ * "value": string | number, "header"?: string }
60
+ */
61
+ assertions: text("assertions").notNull().default("[]"),
62
+ followRedirects: integer("follow_redirects", { mode: "boolean" })
63
+ .notNull()
64
+ .default(true),
65
+ /** Alert severity when the monitor fails. */
66
+ severity: text("severity", { enum: ["warning", "critical"] })
67
+ .notNull()
68
+ .default("critical"),
69
+ /** Notification channels as JSON (e.g. ["inbox","email","slack","webhook"]). */
70
+ channels: text("channels").notNull().default('["inbox"]'),
71
+ /** Email recipients as JSON array of addresses. */
72
+ emailRecipients: text("email_recipients").notNull().default("[]"),
73
+ /** Minutes to suppress repeat alerts while an incident is ongoing. */
74
+ cooldownMinutes: integer("cooldown_minutes").notNull().default(15),
75
+ enabled: integer("enabled", { mode: "boolean" }).notNull().default(true),
76
+
77
+ // ---- Mutable status fields (updated by the runner) ----
78
+ /** up | down | degraded | error | unknown | running */
79
+ lastStatus: text("last_status"),
80
+ lastCheckedAt: text("last_checked_at"),
81
+ lastSuccessAt: text("last_success_at"),
82
+ lastError: text("last_error"),
83
+ lastLatencyMs: integer("last_latency_ms"),
84
+ lastStatusCode: integer("last_status_code"),
85
+ consecutiveFailures: integer("consecutive_failures").notNull().default(0),
86
+
87
+ createdAt: text("created_at").notNull().default(now()),
88
+ updatedAt: text("updated_at").notNull().default(now()),
89
+ ...ownableColumns(),
90
+ });
91
+
92
+ /**
93
+ * Historical probe results. Bounded retention is enforced by the sweep job
94
+ * (server/jobs/uptime-monitors.ts) so this table cannot grow unbounded.
95
+ */
96
+ export const monitorCheckResults = table("monitor_check_results", {
97
+ id: text("id").primaryKey(),
98
+ monitorId: text("monitor_id").notNull(),
99
+ checkedAt: text("checked_at").notNull(),
100
+ ok: integer("ok", { mode: "boolean" }).notNull(),
101
+ /** Classification for this probe: up | down | degraded | error. */
102
+ status: text("status").notNull().default("up"),
103
+ statusCode: integer("status_code"),
104
+ latencyMs: integer("latency_ms"),
105
+ error: text("error"),
106
+ /** JSON array of human-readable assertion failures. */
107
+ failedAssertions: text("failed_assertions").notNull().default("[]"),
108
+ createdAt: text("created_at").notNull().default(now()),
109
+ ...ownableColumns(),
110
+ });
111
+
112
+ /**
113
+ * One incident per continuous failure streak. `resolvedAt` null = ongoing.
114
+ * Mirrors analyticsAlertIncidents.
115
+ */
116
+ export const monitorIncidents = table("monitor_incidents", {
117
+ id: text("id").primaryKey(),
118
+ monitorId: text("monitor_id").notNull(),
119
+ startedAt: text("started_at").notNull(),
120
+ resolvedAt: text("resolved_at"),
121
+ /** down | degraded — the classification at incident open. */
122
+ status: text("status").notNull().default("down"),
123
+ severity: text("severity").notNull().default("critical"),
124
+ /** Short summary of what failed (status code / failed assertions). */
125
+ cause: text("cause").notNull().default(""),
126
+ lastError: text("last_error"),
127
+ notificationId: text("notification_id"),
128
+ checksFailed: integer("checks_failed").notNull().default(1),
129
+ createdAt: text("created_at").notNull().default(now()),
130
+ ...ownableColumns(),
131
+ });
132
+
133
+ /**
134
+ * Owner-authored public status page. A status page bundles a set of the owner's
135
+ * monitors under a public `slug` (`/status/<slug>`) and renders their SAFE
136
+ * aggregate health (status, uptime %s, colored timelines) to anyone with the
137
+ * link — but only when `published` is true. The public read
138
+ * (server/lib/status-pages.ts `getPublicStatusPage`) strictly filters to
139
+ * published pages and the page owner's included monitors, and never leaks
140
+ * monitor URLs/headers/assertions/alert config unless a per-monitor "show URL"
141
+ * opt-in is set.
142
+ *
143
+ * `monitors` is a JSON array of
144
+ * { monitorId: string; order: number; displayName?: string | null;
145
+ * showUrl?: boolean }
146
+ * kept additive so page layout can grow without a join table migration.
147
+ */
148
+ export const statusPages = table("status_pages", {
149
+ id: text("id").primaryKey(),
150
+ /** Public, globally-unique URL slug (`/status/<slug>`). */
151
+ slug: text("slug").notNull(),
152
+ title: text("title").notNull(),
153
+ description: text("description"),
154
+ /** Only published pages are readable by the unauthenticated public route. */
155
+ published: integer("published", { mode: "boolean" }).notNull().default(false),
156
+ // ---- Layout options ----
157
+ showUptimeBars: integer("show_uptime_bars", { mode: "boolean" })
158
+ .notNull()
159
+ .default(true),
160
+ showOverallUptime: integer("show_overall_uptime", { mode: "boolean" })
161
+ .notNull()
162
+ .default(true),
163
+ showResponseTime: integer("show_response_time", { mode: "boolean" })
164
+ .notNull()
165
+ .default(false),
166
+ density: text("density", { enum: ["comfortable", "compact"] })
167
+ .notNull()
168
+ .default("comfortable"),
169
+ alignment: text("alignment", { enum: ["left", "center"] })
170
+ .notNull()
171
+ .default("left"),
172
+ /** JSON array of included monitors with order + optional display overrides. */
173
+ monitors: text("monitors").notNull().default("[]"),
174
+ createdAt: text("created_at").notNull().default(now()),
175
+ updatedAt: text("updated_at").notNull().default(now()),
176
+ ...ownableColumns(),
177
+ });
@@ -9,6 +9,12 @@ import {
9
9
  uniqueIndex,
10
10
  } from "@agent-native/core/db/schema";
11
11
 
12
+ // Feature-owned schema modules. Re-exported so their tables join this app's
13
+ // Drizzle schema namespace (schema.<table>). Each file is owned by a single
14
+ // feature so parallel work never collides on this shared file.
15
+ export * from "./schema-monitoring.js";
16
+ export * from "./schema-errors.js";
17
+
12
18
  /**
13
19
  * Dashboards table — covers both Explorer and SQL dashboards. The
14
20
  * distinction lives in `kind` and the shape of the `config` JSON blob.