@agent-native/core 0.90.11 → 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 (315) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +22 -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/run-ownership.ts +29 -1
  6. package/corpus/core/src/changelog/parse.ts +78 -0
  7. package/corpus/core/src/chat-threads/schema.ts +43 -0
  8. package/corpus/core/src/chat-threads/store.ts +144 -12
  9. package/corpus/core/src/cli/workspace-dev.ts +25 -5
  10. package/corpus/core/src/client/AgentPanel.tsx +79 -14
  11. package/corpus/core/src/client/AssistantChat.tsx +359 -425
  12. package/corpus/core/src/client/analytics-session.ts +70 -0
  13. package/corpus/core/src/client/analytics.ts +175 -49
  14. package/corpus/core/src/client/chat/message-components.tsx +22 -2
  15. package/corpus/core/src/client/components/ui/message-scroller.tsx +131 -0
  16. package/corpus/core/src/client/conversation/AgentConversation.tsx +63 -41
  17. package/corpus/core/src/client/error-capture.ts +616 -0
  18. package/corpus/core/src/client/index.ts +12 -0
  19. package/corpus/core/src/client/session-replay.ts +57 -7
  20. package/corpus/core/src/client/settings/SettingsPanel.tsx +123 -1
  21. package/corpus/core/src/client/settings/SettingsTabsPage.tsx +292 -45
  22. package/corpus/core/src/client/settings/index.ts +1 -0
  23. package/corpus/core/src/client/sharing/ShareButton.tsx +14 -11
  24. package/corpus/core/src/client/sharing/ShareDialog.tsx +13 -10
  25. package/corpus/core/src/mcp/builtin-tools.ts +29 -2
  26. package/corpus/core/src/server/agent-chat-plugin.ts +174 -79
  27. package/corpus/core/src/server/onboarding-html.ts +28 -16
  28. package/corpus/core/src/sharing/actions/list-resource-shares.ts +45 -1
  29. package/corpus/core/src/sharing/actions/share-resource.ts +9 -0
  30. package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -2
  31. package/corpus/core/src/templates/workspace-core/.agents/skills/changelog/SKILL.md +9 -6
  32. package/corpus/core/src/vite/client.ts +217 -35
  33. package/corpus/templates/analytics/.agents/skills/adhoc-analysis/SKILL.md +8 -7
  34. package/corpus/templates/analytics/.agents/skills/analysis-workspace/SKILL.md +14 -10
  35. package/corpus/templates/analytics/.agents/skills/bigquery/SKILL.md +15 -15
  36. package/corpus/templates/analytics/.agents/skills/cross-source-analysis/SKILL.md +1 -0
  37. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +38 -22
  38. package/corpus/templates/analytics/.agents/skills/data-programs/SKILL.md +114 -61
  39. package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +1 -0
  40. package/corpus/templates/analytics/.agents/skills/gong/SKILL.md +7 -7
  41. package/corpus/templates/analytics/.agents/skills/hubspot/SKILL.md +1 -0
  42. package/corpus/templates/analytics/.agents/skills/prometheus/SKILL.md +1 -1
  43. package/corpus/templates/analytics/.builder/skills/bigquery/SKILL.md +17 -17
  44. package/corpus/templates/analytics/.builder/skills/gcloud/SKILL.md +5 -5
  45. package/corpus/templates/analytics/.builder/skills/github/SKILL.md +7 -7
  46. package/corpus/templates/analytics/.builder/skills/gong/SKILL.md +12 -12
  47. package/corpus/templates/analytics/.builder/skills/grafana/SKILL.md +7 -7
  48. package/corpus/templates/analytics/.builder/skills/sentry/SKILL.md +7 -7
  49. package/corpus/templates/analytics/.builder/skills/slack/SKILL.md +6 -6
  50. package/corpus/templates/analytics/.builder/skills/stripe/SKILL.md +7 -7
  51. package/corpus/templates/analytics/AGENTS.md +47 -2
  52. package/corpus/templates/analytics/actions/add-status-page-monitor.ts +36 -0
  53. package/corpus/templates/analytics/actions/capture-test-error.ts +33 -0
  54. package/corpus/templates/analytics/actions/delete-monitor.ts +24 -0
  55. package/corpus/templates/analytics/actions/delete-status-page.ts +23 -0
  56. package/corpus/templates/analytics/actions/get-error-issue.ts +36 -0
  57. package/corpus/templates/analytics/actions/get-monitor-stats.ts +55 -0
  58. package/corpus/templates/analytics/actions/get-monitor.ts +27 -0
  59. package/corpus/templates/analytics/actions/get-public-status-page.ts +41 -0
  60. package/corpus/templates/analytics/actions/get-status-page.ts +29 -0
  61. package/corpus/templates/analytics/actions/list-error-issues.ts +40 -0
  62. package/corpus/templates/analytics/actions/list-monitors.ts +21 -0
  63. package/corpus/templates/analytics/actions/list-status-pages.ts +21 -0
  64. package/corpus/templates/analytics/actions/match-error-issues.ts +51 -0
  65. package/corpus/templates/analytics/actions/navigate.ts +58 -4
  66. package/corpus/templates/analytics/actions/remove-status-page-monitor.ts +22 -0
  67. package/corpus/templates/analytics/actions/reorder-status-page-monitors.ts +25 -0
  68. package/corpus/templates/analytics/actions/resolve-error-issue.ts +38 -0
  69. package/corpus/templates/analytics/actions/run-monitor-check.ts +23 -0
  70. package/corpus/templates/analytics/actions/save-analysis.ts +1 -0
  71. package/corpus/templates/analytics/actions/save-monitor.ts +145 -0
  72. package/corpus/templates/analytics/actions/save-status-page.ts +47 -0
  73. package/corpus/templates/analytics/actions/view-screen.ts +212 -0
  74. package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -0
  75. package/corpus/templates/analytics/app/components/layout/Layout.tsx +10 -1
  76. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +134 -39
  77. package/corpus/templates/analytics/app/components/monitoring/PublicStatusView.tsx +351 -0
  78. package/corpus/templates/analytics/app/components/monitoring/ResponseTimeChart.tsx +174 -0
  79. package/corpus/templates/analytics/app/components/monitoring/UptimeStatCards.tsx +85 -0
  80. package/corpus/templates/analytics/app/components/monitoring/UptimeTimelineBars.tsx +106 -0
  81. package/corpus/templates/analytics/app/components/monitoring/chart-utils.ts +101 -0
  82. package/corpus/templates/analytics/app/components/monitoring/index.ts +28 -0
  83. package/corpus/templates/analytics/app/components/monitoring/types.ts +42 -0
  84. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +34 -0
  85. package/corpus/templates/analytics/app/i18n/zh-TW.ts +6 -0
  86. package/corpus/templates/analytics/app/i18n-data.ts +33 -0
  87. package/corpus/templates/analytics/app/pages/DataSources.tsx +28 -0
  88. package/corpus/templates/analytics/app/pages/Settings.tsx +77 -9
  89. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +3 -3
  90. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/dashboard-layout.ts +7 -0
  91. package/corpus/templates/analytics/app/pages/monitoring/ErrorsPanel.tsx +205 -0
  92. package/corpus/templates/analytics/app/pages/monitoring/MonitoringPage.tsx +100 -0
  93. package/corpus/templates/analytics/app/pages/monitoring/UptimePanel.tsx +475 -0
  94. package/corpus/templates/analytics/app/pages/monitoring/errors/IssueDetail.tsx +372 -0
  95. package/corpus/templates/analytics/app/pages/monitoring/errors/IssueList.tsx +360 -0
  96. package/corpus/templates/analytics/app/pages/monitoring/errors/Sparkline.tsx +55 -0
  97. package/corpus/templates/analytics/app/pages/monitoring/errors/i18n.ts +106 -0
  98. package/corpus/templates/analytics/app/pages/monitoring/errors/types.ts +75 -0
  99. package/corpus/templates/analytics/app/pages/monitoring/errors/utils.ts +132 -0
  100. package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorDetail.tsx +535 -0
  101. package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorFormPage.tsx +1026 -0
  102. package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorList.tsx +311 -0
  103. package/corpus/templates/analytics/app/pages/monitoring/uptime/i18n.ts +235 -0
  104. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/StatusPageEditor.tsx +661 -0
  105. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/StatusPagesView.tsx +355 -0
  106. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/i18n.ts +106 -0
  107. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/slug.ts +24 -0
  108. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/types.ts +20 -0
  109. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-summary.ts +87 -0
  110. package/corpus/templates/analytics/app/pages/monitoring/uptime/types.ts +161 -0
  111. package/corpus/templates/analytics/app/pages/monitoring/uptime/utils.ts +210 -0
  112. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +76 -1
  113. package/corpus/templates/analytics/app/pages/sessions/SessionDevToolsPanel.tsx +74 -9
  114. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +197 -20
  115. package/corpus/templates/analytics/app/root.tsx +33 -1
  116. package/corpus/templates/analytics/app/routes/monitoring._index.tsx +10 -0
  117. package/corpus/templates/analytics/app/routes/status.$slug.tsx +118 -0
  118. package/corpus/templates/analytics/changelog/2026-07-08-add-uptime-monitors-that-ping-your-urls-and-alert-you-when-t.md +6 -0
  119. package/corpus/templates/analytics/changelog/2026-07-08-analytics-chats-keep-large-data-dictionaries-compact-so-prov.md +6 -0
  120. package/corpus/templates/analytics/changelog/2026-07-08-create-public-status-pages-that-share-the-live-health-of-cho.md +6 -0
  121. package/corpus/templates/analytics/changelog/2026-07-08-dashboard-extension-panels-use-clearer-open-copy.md +6 -0
  122. package/corpus/templates/analytics/changelog/2026-07-08-error-capture.md +6 -0
  123. package/corpus/templates/analytics/changelog/2026-07-08-fixed-single-panel-dashboard-drags-so-they-no-longer-rewrite.md +6 -0
  124. package/corpus/templates/analytics/changelog/2026-07-08-jump-straight-from-an-error-in-a-session-recording-to-its-fu.md +6 -0
  125. package/corpus/templates/analytics/changelog/2026-07-08-monitor-detail-and-list-now-show-colorful-uptime-timelines-r.md +6 -0
  126. package/corpus/templates/analytics/changelog/2026-07-08-pinned-ask-chats-now-show-a-pin-icon-in-the-sidebar.md +6 -0
  127. package/corpus/templates/analytics/changelog/2026-07-08-publish-a-public-uptime-status-page-with-colorful-uptime-tim.md +6 -0
  128. package/corpus/templates/analytics/changelog/2026-07-08-sessions-now-hide-visitor-emails-in-demo-mode-and-show-clean.md +6 -0
  129. package/corpus/templates/analytics/changelog/2026-07-08-settings-are-cleaner-searchable-and-alerts-have-their-own-tab.md +5 -0
  130. package/corpus/templates/analytics/changelog/2026-07-08-sidebar-sections-stay-collapsed-until-opened.md +5 -0
  131. package/corpus/templates/analytics/changelog/2026-07-08-the-uptime-monitor-list-now-has-a-current-status-overview-wi.md +6 -0
  132. package/corpus/templates/analytics/docs/error-capture.md +172 -0
  133. package/corpus/templates/analytics/docs/uptime-monitoring.md +150 -0
  134. package/corpus/templates/analytics/server/db/schema-errors.ts +150 -0
  135. package/corpus/templates/analytics/server/db/schema-monitoring.ts +177 -0
  136. package/corpus/templates/analytics/server/db/schema.ts +6 -0
  137. package/corpus/templates/analytics/server/jobs/uptime-monitors.ts +123 -0
  138. package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +41 -0
  139. package/corpus/templates/analytics/server/lib/data-dictionary-context.ts +55 -12
  140. package/corpus/templates/analytics/server/lib/error-capture.ts +1331 -0
  141. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +47 -1
  142. package/corpus/templates/analytics/server/lib/monitor-stats.ts +494 -0
  143. package/corpus/templates/analytics/server/lib/status-pages.ts +798 -0
  144. package/corpus/templates/analytics/server/lib/uptime-monitors.ts +1665 -0
  145. package/corpus/templates/analytics/server/plugins/agent-chat.ts +7 -37
  146. package/corpus/templates/analytics/server/plugins/auth.ts +11 -1
  147. package/corpus/templates/analytics/server/plugins/db.ts +408 -0
  148. package/corpus/templates/analytics/server/plugins/uptime-monitor-jobs.ts +63 -0
  149. package/corpus/templates/assets/app/routes/_index.tsx +1 -1
  150. package/corpus/templates/assets/app/routes/settings.tsx +22 -1
  151. package/corpus/templates/assets/changelog/2026-07-08-recent-drafts-keep-comfortable-side-padding.md +6 -0
  152. package/corpus/templates/assets/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  153. package/corpus/templates/brain/app/routes/settings.tsx +43 -5
  154. package/corpus/templates/brain/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  155. package/corpus/templates/calendar/app/pages/Settings.tsx +44 -6
  156. package/corpus/templates/calendar/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  157. package/corpus/templates/chat/app/routes/settings.tsx +16 -1
  158. package/corpus/templates/chat/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  159. package/corpus/templates/clips/actions/lib/audio-only-transcription.ts +79 -37
  160. package/corpus/templates/clips/app/components/player/player-controls.tsx +35 -0
  161. package/corpus/templates/clips/app/components/player/video-player.tsx +162 -18
  162. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +63 -6
  163. package/corpus/templates/clips/app/routes/record.tsx +18 -1
  164. package/corpus/templates/clips/changelog/2026-07-07-shared-clips-start-playback-reliably-from-the-first-play-click.md +6 -0
  165. package/corpus/templates/clips/changelog/2026-07-08-chrome-extension-camera-and-microphone-menus-now-show-which-.md +6 -0
  166. package/corpus/templates/clips/changelog/2026-07-08-chrome-extension-copies-new-clip-links-after-saving.md +6 -0
  167. package/corpus/templates/clips/changelog/2026-07-08-chrome-extension-recordings-now-continue-after-granting-came.md +6 -0
  168. package/corpus/templates/clips/changelog/2026-07-08-mobile-shared-clips-now-have-loom-style-tap-and-skip-controls.md +6 -0
  169. package/corpus/templates/clips/changelog/2026-07-08-recordings-and-uploads-copy-links-after-saving.md +6 -0
  170. package/corpus/templates/clips/changelog/2026-07-08-settings-are-cleaner-searchable-and-collapse-s3-with-builder.md +5 -0
  171. package/corpus/templates/clips/changelog/2026-07-08-transcripts-are-more-reliable-for-longer-desktop-recordings-.md +6 -0
  172. package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -0
  173. package/corpus/templates/clips/chrome-extension/src/background.ts +162 -13
  174. package/corpus/templates/clips/chrome-extension/src/content-script.ts +14 -0
  175. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +36 -0
  176. package/corpus/templates/clips/chrome-extension/src/overlay.ts +99 -25
  177. package/corpus/templates/clips/chrome-extension/src/permission.ts +63 -14
  178. package/corpus/templates/clips/chrome-extension/src/popup.ts +123 -23
  179. package/corpus/templates/content/actions/_builder-cms-read-client.ts +47 -0
  180. package/corpus/templates/content/actions/_database-source-utils.ts +33 -4
  181. package/corpus/templates/content/actions/add-content-database-source-field-property.ts +214 -29
  182. package/corpus/templates/content/actions/attach-content-database-source.ts +3 -0
  183. package/corpus/templates/content/actions/change-content-database-source-role.ts +1 -0
  184. package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +42 -32
  185. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +352 -81
  186. package/corpus/templates/content/app/components/editor/database/settings.tsx +49 -24
  187. package/corpus/templates/content/app/routes/_app.settings.tsx +19 -1
  188. package/corpus/templates/content/changelog/2026-07-07-builder-source-tag-fields-now-import-as-multi-select.md +6 -0
  189. package/corpus/templates/content/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  190. package/corpus/templates/content/shared/api.ts +3 -0
  191. package/corpus/templates/content/shared/properties.ts +42 -0
  192. package/corpus/templates/design/actions/generate-design.ts +3 -0
  193. package/corpus/templates/design/actions/get-design-system.ts +147 -1
  194. package/corpus/templates/design/app/routes/settings.tsx +16 -1
  195. package/corpus/templates/design/changelog/2026-07-08-design-generation-now-follows-hydrated-builder-design-system.md +6 -0
  196. package/corpus/templates/design/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  197. package/corpus/templates/dispatch/app/routes/settings.tsx +23 -2
  198. package/corpus/templates/dispatch/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  199. package/corpus/templates/forms/app/routes/_app.settings.tsx +16 -1
  200. package/corpus/templates/forms/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  201. package/corpus/templates/macros/app/routes/settings.tsx +16 -1
  202. package/corpus/templates/macros/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  203. package/corpus/templates/mail/app/components/settings/GmailFiltersSection.tsx +1 -1
  204. package/corpus/templates/mail/app/components/settings/SnippetsSection.tsx +1 -1
  205. package/corpus/templates/mail/app/pages/SettingsPage.tsx +123 -105
  206. package/corpus/templates/mail/changelog/2026-07-08-settings-redesigned-with-a-consistent-searchable-layout.md +5 -0
  207. package/corpus/templates/plan/app/routes/settings.tsx +23 -2
  208. package/corpus/templates/plan/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  209. package/corpus/templates/slides/actions/add-slide.ts +1 -0
  210. package/corpus/templates/slides/actions/get-design-system.ts +147 -1
  211. package/corpus/templates/slides/app/pages/Index.tsx +46 -1
  212. package/corpus/templates/slides/app/routes/settings.tsx +16 -1
  213. package/corpus/templates/slides/changelog/2026-07-08-deck-generation-now-follows-hydrated-builder-design-system-g.md +6 -0
  214. package/corpus/templates/slides/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  215. package/dist/agent/run-ownership.d.ts +6 -0
  216. package/dist/agent/run-ownership.d.ts.map +1 -1
  217. package/dist/agent/run-ownership.js +11 -1
  218. package/dist/agent/run-ownership.js.map +1 -1
  219. package/dist/changelog/parse.d.ts +7 -0
  220. package/dist/changelog/parse.d.ts.map +1 -1
  221. package/dist/changelog/parse.js +64 -0
  222. package/dist/changelog/parse.js.map +1 -1
  223. package/dist/chat-threads/schema.d.ts +445 -0
  224. package/dist/chat-threads/schema.d.ts.map +1 -0
  225. package/dist/chat-threads/schema.js +39 -0
  226. package/dist/chat-threads/schema.js.map +1 -0
  227. package/dist/chat-threads/store.d.ts +12 -0
  228. package/dist/chat-threads/store.d.ts.map +1 -1
  229. package/dist/chat-threads/store.js +99 -10
  230. package/dist/chat-threads/store.js.map +1 -1
  231. package/dist/cli/workspace-dev.d.ts.map +1 -1
  232. package/dist/cli/workspace-dev.js +20 -5
  233. package/dist/cli/workspace-dev.js.map +1 -1
  234. package/dist/client/AgentPanel.d.ts.map +1 -1
  235. package/dist/client/AgentPanel.js +35 -7
  236. package/dist/client/AgentPanel.js.map +1 -1
  237. package/dist/client/AssistantChat.d.ts.map +1 -1
  238. package/dist/client/AssistantChat.js +105 -183
  239. package/dist/client/AssistantChat.js.map +1 -1
  240. package/dist/client/analytics-session.d.ts +3 -0
  241. package/dist/client/analytics-session.d.ts.map +1 -0
  242. package/dist/client/analytics-session.js +66 -0
  243. package/dist/client/analytics-session.js.map +1 -0
  244. package/dist/client/analytics.d.ts +32 -0
  245. package/dist/client/analytics.d.ts.map +1 -1
  246. package/dist/client/analytics.js +116 -46
  247. package/dist/client/analytics.js.map +1 -1
  248. package/dist/client/chat/message-components.d.ts +2 -1
  249. package/dist/client/chat/message-components.d.ts.map +1 -1
  250. package/dist/client/chat/message-components.js +16 -6
  251. package/dist/client/chat/message-components.js.map +1 -1
  252. package/dist/client/components/ui/message-scroller.d.ts +16 -0
  253. package/dist/client/components/ui/message-scroller.d.ts.map +1 -0
  254. package/dist/client/components/ui/message-scroller.js +25 -0
  255. package/dist/client/components/ui/message-scroller.js.map +1 -0
  256. package/dist/client/conversation/AgentConversation.d.ts +1 -1
  257. package/dist/client/conversation/AgentConversation.d.ts.map +1 -1
  258. package/dist/client/conversation/AgentConversation.js +3 -8
  259. package/dist/client/conversation/AgentConversation.js.map +1 -1
  260. package/dist/client/error-capture.d.ts +99 -0
  261. package/dist/client/error-capture.d.ts.map +1 -0
  262. package/dist/client/error-capture.js +437 -0
  263. package/dist/client/error-capture.js.map +1 -0
  264. package/dist/client/index.d.ts +2 -2
  265. package/dist/client/index.d.ts.map +1 -1
  266. package/dist/client/index.js +3 -1
  267. package/dist/client/index.js.map +1 -1
  268. package/dist/client/session-replay.d.ts +22 -0
  269. package/dist/client/session-replay.d.ts.map +1 -1
  270. package/dist/client/session-replay.js +45 -4
  271. package/dist/client/session-replay.js.map +1 -1
  272. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  273. package/dist/client/settings/SettingsPanel.js +100 -5
  274. package/dist/client/settings/SettingsPanel.js.map +1 -1
  275. package/dist/client/settings/SettingsTabsPage.d.ts +49 -1
  276. package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -1
  277. package/dist/client/settings/SettingsTabsPage.js +131 -19
  278. package/dist/client/settings/SettingsTabsPage.js.map +1 -1
  279. package/dist/client/settings/index.d.ts +1 -1
  280. package/dist/client/settings/index.d.ts.map +1 -1
  281. package/dist/client/settings/index.js.map +1 -1
  282. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  283. package/dist/client/sharing/ShareButton.js +13 -8
  284. package/dist/client/sharing/ShareButton.js.map +1 -1
  285. package/dist/client/sharing/ShareDialog.d.ts.map +1 -1
  286. package/dist/client/sharing/ShareDialog.js +12 -7
  287. package/dist/client/sharing/ShareDialog.js.map +1 -1
  288. package/dist/collab/struct-routes.d.ts +1 -1
  289. package/dist/mcp/builtin-tools.d.ts.map +1 -1
  290. package/dist/mcp/builtin-tools.js +21 -2
  291. package/dist/mcp/builtin-tools.js.map +1 -1
  292. package/dist/notifications/routes.d.ts +1 -1
  293. package/dist/org/schema.d.ts +15 -15
  294. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  295. package/dist/resources/handlers.d.ts +3 -3
  296. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  297. package/dist/server/agent-chat-plugin.js +109 -73
  298. package/dist/server/agent-chat-plugin.js.map +1 -1
  299. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  300. package/dist/server/onboarding-html.d.ts.map +1 -1
  301. package/dist/server/onboarding-html.js +28 -16
  302. package/dist/server/onboarding-html.js.map +1 -1
  303. package/dist/sharing/actions/list-resource-shares.js +30 -1
  304. package/dist/sharing/actions/list-resource-shares.js.map +1 -1
  305. package/dist/sharing/actions/share-resource.js +6 -0
  306. package/dist/sharing/actions/share-resource.js.map +1 -1
  307. package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -2
  308. package/dist/templates/workspace-core/.agents/skills/changelog/SKILL.md +9 -6
  309. package/dist/vite/client.d.ts.map +1 -1
  310. package/dist/vite/client.js +192 -30
  311. package/dist/vite/client.js.map +1 -1
  312. package/docs/content/toolkit-settings.mdx +56 -3
  313. package/package.json +2 -1
  314. package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -2
  315. package/src/templates/workspace-core/.agents/skills/changelog/SKILL.md +9 -6
@@ -15,6 +15,7 @@ import {
15
15
  IconSearch,
16
16
  IconArchive,
17
17
  IconActivity,
18
+ IconHeartbeat,
18
19
  IconPin,
19
20
  IconPlus,
20
21
  IconLock,
@@ -136,6 +137,7 @@ import { NewDashboardDialog } from "./NewDashboardDialog";
136
137
  type AnalysisHiddenFilter = "visible" | "hidden";
137
138
 
138
139
  const SIDEBAR_PREVIEW_COUNT = 5;
140
+ const ASK_OPEN_KEY = "analytics-sidebar-ask-open";
139
141
  const DASHBOARD_SORT_MODE_KEY = "dashboard-sort-mode";
140
142
  const ANALYSIS_SORT_MODE_KEY = "analysis-sort-mode";
141
143
  const DASHBOARDS_OPEN_KEY = "analytics-sidebar-dashboards-open";
@@ -169,12 +171,16 @@ const bottomItems = [
169
171
  { icon: IconSettings, labelKey: "navigation.settings", href: "/settings" },
170
172
  ];
171
173
 
172
- function getStoredBoolean(key: string, fallback: boolean): boolean {
173
- if (typeof window === "undefined") return fallback;
174
- const raw = window.localStorage.getItem(key);
175
- if (raw === "true") return true;
176
- if (raw === "false") return false;
177
- return fallback;
174
+ function getStoredBooleanPreference(key: string): boolean | null {
175
+ if (typeof window === "undefined") return null;
176
+ try {
177
+ const raw = window.localStorage.getItem(key);
178
+ if (raw === "true") return true;
179
+ if (raw === "false") return false;
180
+ } catch {
181
+ // localStorage unavailable — ignore, section state is best-effort.
182
+ }
183
+ return null;
178
184
  }
179
185
 
180
186
  function setStoredBoolean(key: string, value: boolean): void {
@@ -1476,7 +1482,15 @@ function AnalyticsChatsSection() {
1476
1482
  onClick={() => openThread(thread.id)}
1477
1483
  className="min-w-0 flex-1 px-2 py-1.5 pe-12 text-start text-xs outline-none focus-visible:ring-2 focus-visible:ring-ring"
1478
1484
  >
1479
- <span className="block truncate">{title}</span>
1485
+ <span className="flex min-w-0 items-center gap-1.5">
1486
+ {thread.pinnedAt ? (
1487
+ <IconPin
1488
+ aria-hidden="true"
1489
+ className="size-3 shrink-0 text-current opacity-60"
1490
+ />
1491
+ ) : null}
1492
+ <span className="block min-w-0 truncate">{title}</span>
1493
+ </span>
1480
1494
  </button>
1481
1495
  </TooltipTrigger>
1482
1496
  <TooltipContent side="right">{title}</TooltipContent>
@@ -1573,13 +1587,30 @@ export function Sidebar({ mobile }: { mobile?: boolean } = {}) {
1573
1587
  const queryClient = useQueryClient();
1574
1588
  const { setTheme } = useTheme();
1575
1589
 
1576
- const [dashOpen, setDashOpen] = useState(() =>
1577
- getStoredBoolean(DASHBOARDS_OPEN_KEY, true),
1590
+ const isAskRoute = location.pathname === "/ask";
1591
+ const activeDashboardId = useMemo(() => {
1592
+ const match = location.pathname.match(/^\/(?:adhoc|dashboards)\/([^/]+)/);
1593
+ if (!match?.[1]) return null;
1594
+ return new URLSearchParams(location.search).get("id") || match[1];
1595
+ }, [location.pathname, location.search]);
1596
+ const activeAnalysisId = useMemo(() => {
1597
+ const match = location.pathname.match(/^\/analyses\/([^/]+)/);
1598
+ return match?.[1] ?? null;
1599
+ }, [location.pathname]);
1600
+ const [askOpen, setAskOpen] = useState(
1601
+ () => getStoredBooleanPreference(ASK_OPEN_KEY) ?? isAskRoute,
1602
+ );
1603
+ const [dashOpen, setDashOpen] = useState(
1604
+ () =>
1605
+ getStoredBooleanPreference(DASHBOARDS_OPEN_KEY) ??
1606
+ activeDashboardId !== null,
1578
1607
  );
1579
1608
  const [dashShowAll, setDashShowAll] = useState(false);
1580
1609
  const [dashFilter, setDashFilter] = useState<SidebarVisibilityFilter>("all");
1581
- const [analysesOpen, setAnalysesOpen] = useState(() =>
1582
- getStoredBoolean(ANALYSES_OPEN_KEY, true),
1610
+ const [analysesOpen, setAnalysesOpen] = useState(
1611
+ () =>
1612
+ getStoredBooleanPreference(ANALYSES_OPEN_KEY) ??
1613
+ activeAnalysisId !== null,
1583
1614
  );
1584
1615
  const [analysesShowAll, setAnalysesShowAll] = useState(false);
1585
1616
  const [analysisFilter, setAnalysisFilter] =
@@ -1681,6 +1712,32 @@ export function Sidebar({ mobile }: { mobile?: boolean } = {}) {
1681
1712
  setAnalysisSortModeState(mode);
1682
1713
  }, []);
1683
1714
 
1715
+ useEffect(() => {
1716
+ if (getStoredBooleanPreference(ASK_OPEN_KEY) === null) {
1717
+ setAskOpen(isAskRoute);
1718
+ }
1719
+ }, [isAskRoute]);
1720
+
1721
+ useEffect(() => {
1722
+ if (getStoredBooleanPreference(DASHBOARDS_OPEN_KEY) === null) {
1723
+ setDashOpen(activeDashboardId !== null);
1724
+ }
1725
+ }, [activeDashboardId]);
1726
+
1727
+ useEffect(() => {
1728
+ if (getStoredBooleanPreference(ANALYSES_OPEN_KEY) === null) {
1729
+ setAnalysesOpen(activeAnalysisId !== null);
1730
+ }
1731
+ }, [activeAnalysisId]);
1732
+
1733
+ const toggleAskOpen = useCallback(() => {
1734
+ setAskOpen((current) => {
1735
+ const next = !current;
1736
+ setStoredBoolean(ASK_OPEN_KEY, next);
1737
+ return next;
1738
+ });
1739
+ }, []);
1740
+
1684
1741
  const toggleDashOpen = useCallback(() => {
1685
1742
  setDashOpen((current) => {
1686
1743
  const next = !current;
@@ -1765,12 +1822,6 @@ export function Sidebar({ mobile }: { mobile?: boolean } = {}) {
1765
1822
  [filteredAnalyses, analysesShowAll],
1766
1823
  );
1767
1824
 
1768
- const activeDashboardId = useMemo(() => {
1769
- const match = location.pathname.match(/^\/(?:adhoc|dashboards)\/([^/]+)/);
1770
- if (!match?.[1]) return null;
1771
- return new URLSearchParams(location.search).get("id") || match[1];
1772
- }, [location.pathname, location.search]);
1773
-
1774
1825
  // Only the active dashboard can display saved views in the sidebar, so avoid
1775
1826
  // issuing one request per dashboard on every sidebar mount.
1776
1827
  const { views: activeDashboardViews = [] } = useDashboardViews(
@@ -2340,6 +2391,12 @@ export function Sidebar({ mobile }: { mobile?: boolean } = {}) {
2340
2391
  href: "/sessions",
2341
2392
  active: location.pathname.startsWith("/sessions"),
2342
2393
  },
2394
+ {
2395
+ icon: IconHeartbeat,
2396
+ label: t("navigation.monitoring"),
2397
+ href: "/monitoring",
2398
+ active: location.pathname.startsWith("/monitoring"),
2399
+ },
2343
2400
  {
2344
2401
  icon: IconActivity,
2345
2402
  label: t("navigation.agents"),
@@ -2480,33 +2537,57 @@ export function Sidebar({ mobile }: { mobile?: boolean } = {}) {
2480
2537
  </div>
2481
2538
  <div className="flex min-h-0 flex-1 flex-col overflow-y-auto overflow-x-hidden py-2">
2482
2539
  <nav className="grid min-w-0 items-start px-2 text-sm font-medium lg:px-4 space-y-1">
2483
- {/* Ask link */}
2484
- <div className="min-w-0 space-y-1">
2485
- <Link
2486
- to="/ask"
2487
- onClick={(event) => {
2488
- if (
2489
- location.pathname !== "/ask" &&
2490
- !event.metaKey &&
2491
- !event.ctrlKey &&
2492
- !event.shiftKey &&
2493
- !event.altKey
2494
- ) {
2495
- event.preventDefault();
2496
- navigateWithAgentChatViewTransition(navigate, "/ask");
2497
- }
2498
- }}
2540
+ {/* Ask section */}
2541
+ <div className="group/section min-w-0 space-y-1">
2542
+ <div
2499
2543
  className={cn(
2500
- "flex items-center gap-3 rounded-lg px-3 py-2 transition-all hover:text-primary",
2501
- location.pathname === "/ask"
2544
+ "flex w-full min-w-0 items-center rounded-lg transition-all hover:text-primary",
2545
+ isAskRoute
2502
2546
  ? "bg-sidebar-accent text-sidebar-accent-foreground"
2503
2547
  : "text-muted-foreground hover:bg-sidebar-accent/50",
2504
2548
  )}
2505
2549
  >
2506
- <IconMessageCircle className="h-4 w-4" />
2507
- {t("navigation.ask")}
2508
- </Link>
2509
- {location.pathname === "/ask" && <AnalyticsChatsSection />}
2550
+ <Link
2551
+ to="/ask"
2552
+ onClick={(event) => {
2553
+ if (
2554
+ !isAskRoute &&
2555
+ !event.metaKey &&
2556
+ !event.ctrlKey &&
2557
+ !event.shiftKey &&
2558
+ !event.altKey
2559
+ ) {
2560
+ event.preventDefault();
2561
+ navigateWithAgentChatViewTransition(navigate, "/ask");
2562
+ }
2563
+ }}
2564
+ className="flex min-w-0 flex-1 items-center gap-3 px-3 py-2"
2565
+ >
2566
+ <IconMessageCircle className="h-4 w-4 shrink-0" />
2567
+ <span className="min-w-0 flex-1 truncate">
2568
+ {t("navigation.ask")}
2569
+ </span>
2570
+ </Link>
2571
+ <button
2572
+ type="button"
2573
+ onClick={toggleAskOpen}
2574
+ className="me-1 flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-muted-foreground/70 hover:bg-sidebar-accent hover:text-foreground"
2575
+ aria-label={
2576
+ askOpen
2577
+ ? t("sidebar.collapseAsk")
2578
+ : t("sidebar.expandAsk")
2579
+ }
2580
+ aria-expanded={askOpen}
2581
+ >
2582
+ <IconChevronDown
2583
+ className={cn(
2584
+ "h-3.5 w-3.5 shrink-0 transition-transform",
2585
+ !askOpen && "-rotate-90",
2586
+ )}
2587
+ />
2588
+ </button>
2589
+ </div>
2590
+ {askOpen && <AnalyticsChatsSection />}
2510
2591
  </div>
2511
2592
 
2512
2593
  {/* Sessions link */}
@@ -2523,6 +2604,20 @@ export function Sidebar({ mobile }: { mobile?: boolean } = {}) {
2523
2604
  {t("navigation.sessions")}
2524
2605
  </Link>
2525
2606
 
2607
+ {/* Monitoring link */}
2608
+ <Link
2609
+ to="/monitoring"
2610
+ className={cn(
2611
+ "flex items-center gap-3 rounded-lg px-3 py-2 transition-all hover:text-primary",
2612
+ location.pathname.startsWith("/monitoring")
2613
+ ? "bg-sidebar-accent text-sidebar-accent-foreground"
2614
+ : "text-muted-foreground hover:bg-sidebar-accent/50",
2615
+ )}
2616
+ >
2617
+ <IconHeartbeat className="h-4 w-4" />
2618
+ {t("navigation.monitoring")}
2619
+ </Link>
2620
+
2526
2621
  {/* Agents link */}
2527
2622
  <Link
2528
2623
  to="/agents"
@@ -0,0 +1,351 @@
1
+ /**
2
+ * Presentational public status page. Pure/client-safe: it takes an already-
3
+ * resolved, sanitized `PublicStatusPage` payload (from the
4
+ * `get-public-status-page` action / SSR loader) and renders the branded status
5
+ * banner, overall uptime cards, per-monitor colored uptime timelines, optional
6
+ * response-time charts, and an incidents section.
7
+ */
8
+ import {
9
+ IconActivity,
10
+ IconAlertCircle,
11
+ IconAlertTriangle,
12
+ IconCircleCheck,
13
+ IconRefresh,
14
+ } from "@tabler/icons-react";
15
+
16
+ import { cn } from "@/lib/utils";
17
+
18
+ import type { PublicStatusPage } from "../../../server/lib/status-pages";
19
+ import { formatLatencyMs, formatUptimePct } from "./chart-utils";
20
+ import { ResponseTimeChart } from "./ResponseTimeChart";
21
+ import { UptimeStatCards } from "./UptimeStatCards";
22
+ import { UptimeTimelineBars } from "./UptimeTimelineBars";
23
+
24
+ type OverallStatus = PublicStatusPage["overall"];
25
+ type PublicMonitor = PublicStatusPage["monitors"][number];
26
+ type MonitorStatus = PublicMonitor["status"];
27
+
28
+ function monitorTone(
29
+ status: MonitorStatus,
30
+ ): "up" | "down" | "degraded" | "neutral" {
31
+ switch (status) {
32
+ case "up":
33
+ return "up";
34
+ case "down":
35
+ case "error":
36
+ return "down";
37
+ case "degraded":
38
+ return "degraded";
39
+ default:
40
+ return "neutral";
41
+ }
42
+ }
43
+
44
+ function toneDotClass(tone: ReturnType<typeof monitorTone>): string {
45
+ switch (tone) {
46
+ case "up":
47
+ return "bg-emerald-500";
48
+ case "down":
49
+ return "bg-red-500";
50
+ case "degraded":
51
+ return "bg-amber-500";
52
+ default:
53
+ return "bg-muted-foreground/40";
54
+ }
55
+ }
56
+
57
+ function toneTextClass(tone: ReturnType<typeof monitorTone>): string {
58
+ switch (tone) {
59
+ case "up":
60
+ return "text-emerald-500";
61
+ case "down":
62
+ return "text-red-500";
63
+ case "degraded":
64
+ return "text-amber-500";
65
+ default:
66
+ return "text-muted-foreground";
67
+ }
68
+ }
69
+
70
+ function monitorStatusLabel(status: MonitorStatus): string {
71
+ switch (status) {
72
+ case "up":
73
+ return "Operational";
74
+ case "down":
75
+ return "Down";
76
+ case "degraded":
77
+ return "Degraded";
78
+ case "error":
79
+ return "Error";
80
+ case "running":
81
+ return "Checking";
82
+ default:
83
+ return "Unknown";
84
+ }
85
+ }
86
+
87
+ const BANNER: Record<
88
+ OverallStatus,
89
+ {
90
+ icon: typeof IconCircleCheck;
91
+ accent: string;
92
+ ring: string;
93
+ iconClass: string;
94
+ title: string;
95
+ }
96
+ > = {
97
+ operational: {
98
+ icon: IconCircleCheck,
99
+ accent: "bg-emerald-500/10",
100
+ ring: "border-emerald-500/30",
101
+ iconClass: "text-emerald-500",
102
+ title: "All systems operational", // i18n-ignore public status page fixed copy
103
+ },
104
+ degraded: {
105
+ icon: IconAlertTriangle,
106
+ accent: "bg-amber-500/10",
107
+ ring: "border-amber-500/30",
108
+ iconClass: "text-amber-500",
109
+ title: "Some systems degraded", // i18n-ignore public status page fixed copy
110
+ },
111
+ down: {
112
+ icon: IconAlertCircle,
113
+ accent: "bg-red-500/10",
114
+ ring: "border-red-500/30",
115
+ iconClass: "text-red-500",
116
+ title: "System outage in progress", // i18n-ignore public status page fixed copy
117
+ },
118
+ unknown: {
119
+ icon: IconActivity,
120
+ accent: "bg-muted",
121
+ ring: "border-border/60",
122
+ iconClass: "text-muted-foreground",
123
+ title: "Status unknown", // i18n-ignore public status page fixed copy
124
+ },
125
+ };
126
+
127
+ function bannerSubtitle(page: PublicStatusPage): string {
128
+ const { up, down, degraded, total } = page.counts;
129
+ if (total === 0) return "No monitors are being tracked on this page yet.";
130
+ if (page.overall === "operational") {
131
+ return `${total} ${total === 1 ? "monitor" : "monitors"} reporting healthy.`;
132
+ }
133
+ const parts: string[] = [];
134
+ if (down > 0) parts.push(`${down} down`);
135
+ if (degraded > 0) parts.push(`${degraded} degraded`);
136
+ if (up > 0) parts.push(`${up} operational`);
137
+ return parts.join(" · ");
138
+ }
139
+
140
+ function formatUpdatedAt(value: string): string {
141
+ const date = new Date(value);
142
+ if (Number.isNaN(date.getTime())) return "just now";
143
+ return date.toLocaleString(undefined, {
144
+ month: "short",
145
+ day: "numeric",
146
+ hour: "numeric",
147
+ minute: "2-digit",
148
+ });
149
+ }
150
+
151
+ export function PublicStatusView({
152
+ page,
153
+ refreshing = false,
154
+ }: {
155
+ page: PublicStatusPage;
156
+ refreshing?: boolean;
157
+ }) {
158
+ const banner = BANNER[page.overall];
159
+ const BannerIcon = banner.icon;
160
+ const centered = page.layout.alignment === "center";
161
+ const compact = page.layout.density === "compact";
162
+
163
+ return (
164
+ <main className="min-h-screen bg-background text-foreground">
165
+ <div
166
+ className={cn(
167
+ "mx-auto w-full max-w-4xl px-5 py-10 sm:px-8 sm:py-14",
168
+ centered && "text-center",
169
+ )}
170
+ >
171
+ {/* Brand + title */}
172
+ <header
173
+ className={cn("flex flex-col gap-1", centered && "items-center")}
174
+ >
175
+ <div className="flex items-center gap-2 text-sm font-medium text-muted-foreground">
176
+ <span className="inline-flex size-5 items-center justify-center rounded-md bg-[var(--brand-amber,#F59E0B)]/15 text-[var(--brand-amber,#F59E0B)]">
177
+ <IconActivity className="size-3.5" />
178
+ </span>
179
+ Status
180
+ </div>
181
+ <h1 className="text-2xl font-semibold tracking-tight sm:text-3xl">
182
+ {page.title}
183
+ </h1>
184
+ {page.description ? (
185
+ <p className="max-w-2xl text-sm text-muted-foreground">
186
+ {page.description}
187
+ </p>
188
+ ) : null}
189
+ </header>
190
+
191
+ {/* Overall banner */}
192
+ <section
193
+ className={cn(
194
+ "mt-6 flex items-center gap-4 rounded-xl border px-5 py-4",
195
+ banner.ring,
196
+ banner.accent,
197
+ centered && "justify-center text-left",
198
+ )}
199
+ >
200
+ <span
201
+ className={cn(
202
+ "inline-flex size-10 shrink-0 items-center justify-center rounded-full bg-background/60",
203
+ banner.iconClass,
204
+ )}
205
+ >
206
+ <BannerIcon className="size-6" />
207
+ </span>
208
+ <div className="min-w-0">
209
+ <div className="text-lg font-semibold">{banner.title}</div>
210
+ <div className="text-sm text-muted-foreground">
211
+ {bannerSubtitle(page)}
212
+ </div>
213
+ </div>
214
+ </section>
215
+
216
+ {/* Overall uptime cards */}
217
+ {page.layout.showOverallUptime && page.monitors.length > 0 ? (
218
+ <section className="mt-6">
219
+ <h2 className="mb-2 text-xs font-medium uppercase tracking-wide text-muted-foreground">
220
+ Overall uptime{/* i18n-ignore public status page fixed copy */}
221
+ </h2>
222
+ <UptimeStatCards windows={page.overallWindows} compact={compact} />
223
+ </section>
224
+ ) : null}
225
+
226
+ {/* Per-monitor list */}
227
+ <section className="mt-8 space-y-3">
228
+ <h2 className="text-xs font-medium uppercase tracking-wide text-muted-foreground">
229
+ Monitors
230
+ </h2>
231
+ {page.monitors.length === 0 ? (
232
+ <div className="rounded-lg border border-dashed border-border/60 bg-muted/20 px-5 py-10 text-center text-sm text-muted-foreground">
233
+ No monitors have been added to this status page yet.
234
+ {/* i18n-ignore public status page fixed copy */}
235
+ </div>
236
+ ) : (
237
+ page.monitors.map((monitor) => {
238
+ const tone = monitorTone(monitor.status);
239
+ return (
240
+ <article
241
+ key={monitor.id}
242
+ className={cn(
243
+ "rounded-xl border border-border/50 bg-card",
244
+ compact ? "p-4" : "p-5",
245
+ )}
246
+ >
247
+ <div className="flex flex-wrap items-center justify-between gap-2">
248
+ <div className="flex min-w-0 items-center gap-2.5">
249
+ <span
250
+ className={cn(
251
+ "size-2.5 shrink-0 rounded-full",
252
+ toneDotClass(tone),
253
+ )}
254
+ />
255
+ <div className="min-w-0">
256
+ <div className="truncate font-medium">
257
+ {monitor.name}
258
+ </div>
259
+ {monitor.host ? (
260
+ <div className="truncate text-xs text-muted-foreground">
261
+ {monitor.url ? (
262
+ <a
263
+ href={monitor.url}
264
+ target="_blank"
265
+ rel="noreferrer noopener nofollow"
266
+ className="hover:text-foreground"
267
+ >
268
+ {monitor.host}
269
+ </a>
270
+ ) : (
271
+ monitor.host
272
+ )}
273
+ </div>
274
+ ) : null}
275
+ </div>
276
+ </div>
277
+ <div className="flex items-center gap-3 text-sm">
278
+ <span className={cn("font-medium", toneTextClass(tone))}>
279
+ {monitorStatusLabel(monitor.status)}
280
+ </span>
281
+ <span className="tabular-nums text-muted-foreground">
282
+ {formatUptimePct(monitor.windows.uptime90d)} (90d)
283
+ </span>
284
+ </div>
285
+ </div>
286
+
287
+ {page.layout.showUptimeBars ? (
288
+ <div className="mt-3">
289
+ <UptimeTimelineBars
290
+ buckets={monitor.timeline}
291
+ heightClassName={compact ? "h-6" : "h-8"}
292
+ ariaLabel={`${monitor.name} uptime over the last 90 days`}
293
+ />
294
+ <div className="mt-1 flex justify-between text-[10px] text-muted-foreground">
295
+ <span>90 days ago</span>
296
+ <span>Today</span>
297
+ </div>
298
+ </div>
299
+ ) : null}
300
+
301
+ {page.layout.showResponseTime &&
302
+ monitor.responseSeries.length > 0 ? (
303
+ <div className="mt-4">
304
+ <div className="mb-1 flex items-center justify-between">
305
+ <span className="text-xs font-medium">
306
+ Response time
307
+ {/* i18n-ignore public status page fixed copy */}
308
+ </span>
309
+ <span className="text-[10px] text-muted-foreground">
310
+ avg {formatLatencyMs(monitor.avgResponseMs)}
311
+ </span>
312
+ </div>
313
+ <ResponseTimeChart
314
+ series={monitor.responseSeries}
315
+ heightClassName="h-[140px]"
316
+ />
317
+ </div>
318
+ ) : null}
319
+ </article>
320
+ );
321
+ })
322
+ )}
323
+ </section>
324
+
325
+ {/* Incidents / status updates */}
326
+ <section className="mt-8">
327
+ <h2 className="mb-2 text-xs font-medium uppercase tracking-wide text-muted-foreground">
328
+ Past incidents{/* i18n-ignore public status page fixed copy */}
329
+ </h2>
330
+ <div className="rounded-lg border border-border/50 bg-card px-5 py-8 text-center text-sm text-muted-foreground">
331
+ No incidents reported.
332
+ {/* i18n-ignore public status page fixed copy */}
333
+ </div>
334
+ </section>
335
+
336
+ {/* Footer: last updated + auto-refresh */}
337
+ <footer
338
+ className={cn(
339
+ "mt-8 flex items-center gap-1.5 text-xs text-muted-foreground",
340
+ centered && "justify-center",
341
+ )}
342
+ >
343
+ <IconRefresh
344
+ className={cn("size-3.5", refreshing && "animate-spin")}
345
+ />
346
+ <span>Last updated {formatUpdatedAt(page.generatedAt)}</span>
347
+ </footer>
348
+ </div>
349
+ </main>
350
+ );
351
+ }