@agent-native/core 0.92.0 → 0.92.2

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 (375) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +20 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/application-state/store.ts +12 -1
  5. package/corpus/core/src/cli/sync-builder-starter-manifest.ts +29 -1
  6. package/corpus/core/src/client/AssistantChat.tsx +27 -14
  7. package/corpus/core/src/client/PoweredByBadge.tsx +1 -8
  8. package/corpus/core/src/client/agent-chat-adapter.ts +37 -10
  9. package/corpus/core/src/client/chat/widgets/DataTableWidget.tsx +52 -1
  10. package/corpus/core/src/client/db-admin/TableEditor.tsx +49 -0
  11. package/corpus/core/src/client/db-admin/export-utils.ts +13 -4
  12. package/corpus/core/src/client/db-admin/useAgentSync.ts +72 -0
  13. package/corpus/core/src/client/error-capture.ts +69 -7
  14. package/corpus/core/src/client/extensions/EmbeddedExtension.tsx +5 -1
  15. package/corpus/core/src/client/extensions/ExtensionViewer.tsx +53 -8
  16. package/corpus/core/src/client/extensions/InlineExtensionFrame.tsx +5 -1
  17. package/corpus/core/src/client/extensions/portable-extension.ts +1 -0
  18. package/corpus/core/src/client/org/OrgSwitcher.tsx +12 -9
  19. package/corpus/core/src/client/org/TeamPage.tsx +77 -71
  20. package/corpus/core/src/client/settings/SettingsPanel.tsx +205 -52
  21. package/corpus/core/src/client/settings/SettingsSection.tsx +8 -1
  22. package/corpus/core/src/client/settings/SettingsTabsPage.tsx +25 -9
  23. package/corpus/core/src/db-admin/agent-tools.ts +8 -2
  24. package/corpus/core/src/db-admin/operations.ts +116 -4
  25. package/corpus/core/src/db-admin/routes.ts +1 -0
  26. package/corpus/core/src/db-admin/types.ts +4 -0
  27. package/corpus/core/src/extensions/html-shell.ts +5 -4
  28. package/corpus/core/src/extensions/routes.ts +10 -0
  29. package/corpus/core/src/navigation/index.ts +1 -1
  30. package/corpus/core/src/notifications/channels.ts +1 -22
  31. package/corpus/core/src/resources/handlers.ts +10 -8
  32. package/corpus/core/src/server/poll.ts +293 -8
  33. package/corpus/core/src/styles/agent-native.css +27 -0
  34. package/corpus/core/src/templates/default/.agents/skills/actions/SKILL.md +5 -0
  35. package/corpus/core/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
  36. package/corpus/core/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
  37. package/corpus/core/src/templates/default/.agents/skills/security/SKILL.md +7 -0
  38. package/corpus/core/src/templates/default/.agents/skills/storing-data/SKILL.md +5 -1
  39. package/corpus/core/src/templates/default/AGENTS.md +4 -2
  40. package/corpus/core/src/templates/headless/AGENTS.md +4 -0
  41. package/corpus/core/src/templates/workspace-core/.agents/skills/actions/SKILL.md +5 -0
  42. package/corpus/core/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
  43. package/corpus/core/src/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +4 -0
  44. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -0
  45. package/corpus/core/src/templates/workspace-core/.agents/skills/performance/SKILL.md +4 -0
  46. package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
  47. package/corpus/core/src/templates/workspace-core/.agents/skills/security/SKILL.md +7 -0
  48. package/corpus/core/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +5 -1
  49. package/corpus/core/src/templates/workspace-core/AGENTS.md +7 -1
  50. package/corpus/core/src/templates/workspace-root/AGENTS.md +7 -1
  51. package/corpus/templates/analytics/.agents/skills/actions/SKILL.md +5 -0
  52. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +10 -0
  53. package/corpus/templates/analytics/.agents/skills/real-time-sync/SKILL.md +1 -1
  54. package/corpus/templates/analytics/.agents/skills/security/SKILL.md +7 -0
  55. package/corpus/templates/analytics/.agents/skills/storing-data/SKILL.md +5 -1
  56. package/corpus/templates/analytics/AGENTS.md +33 -14
  57. package/corpus/templates/analytics/actions/capture-test-error.ts +4 -0
  58. package/corpus/templates/analytics/actions/get-analytics-alert-rule-defaults.ts +23 -0
  59. package/corpus/templates/analytics/actions/get-error-issue.ts +1 -1
  60. package/corpus/templates/analytics/actions/list-analysis-revisions.ts +40 -0
  61. package/corpus/templates/analytics/actions/list-dashboard-revisions.ts +40 -0
  62. package/corpus/templates/analytics/actions/list-dashboard-usage-stats.ts +299 -0
  63. package/corpus/templates/analytics/actions/navigate.ts +4 -2
  64. package/corpus/templates/analytics/actions/restore-analysis-revision.ts +43 -0
  65. package/corpus/templates/analytics/actions/restore-dashboard-revision.ts +68 -0
  66. package/corpus/templates/analytics/actions/save-analytics-alert-rule.ts +14 -0
  67. package/corpus/templates/analytics/actions/save-monitor.ts +1 -1
  68. package/corpus/templates/analytics/actions/view-screen.ts +24 -0
  69. package/corpus/templates/analytics/app/components/analysis/AnalysisHistoryPanel.tsx +181 -0
  70. package/corpus/templates/analytics/app/components/dashboard/DashboardHistoryPanel.tsx +184 -0
  71. package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +22 -16
  72. package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -1
  73. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +27 -21
  74. package/corpus/templates/analytics/app/hooks/use-analysis-revisions.ts +43 -0
  75. package/corpus/templates/analytics/app/hooks/use-dashboard-chat-context.ts +110 -0
  76. package/corpus/templates/analytics/app/hooks/use-dashboard-revisions.ts +43 -0
  77. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +8 -3
  78. package/corpus/templates/analytics/app/i18n/zh-TW.ts +64 -2
  79. package/corpus/templates/analytics/app/i18n-data.ts +783 -3
  80. package/corpus/templates/analytics/app/pages/Agents.tsx +359 -19
  81. package/corpus/templates/analytics/app/pages/Settings.tsx +3 -2
  82. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +34 -1
  83. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +28 -0
  84. package/corpus/templates/analytics/app/pages/analyses/AnalysisDetail.tsx +18 -1
  85. package/corpus/templates/analytics/app/pages/monitoring/ErrorsPanel.tsx +7 -10
  86. package/corpus/templates/analytics/app/pages/monitoring/errors/IssueDetail.tsx +479 -23
  87. package/corpus/templates/analytics/app/pages/monitoring/errors/IssueList.tsx +0 -9
  88. package/corpus/templates/analytics/app/pages/monitoring/errors/i18n.ts +11 -0
  89. package/corpus/templates/analytics/app/pages/monitoring/errors/types.ts +9 -1
  90. package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorFormPage.tsx +6 -3
  91. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +26 -30
  92. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +9 -99
  93. package/corpus/templates/analytics/app/pages/settings/AlertRulesSettingsCard.tsx +262 -104
  94. package/corpus/templates/analytics/app/routes/team.tsx +1 -1
  95. package/corpus/templates/analytics/changelog/2026-07-08-admins-can-audit-dashboard-usage-ownership-and-cleanup-signa.md +6 -0
  96. package/corpus/templates/analytics/changelog/2026-07-08-agent-monitoring-stays-available-to-non-admins.md +6 -0
  97. package/corpus/templates/analytics/changelog/2026-07-08-alert-emails-now-show-the-message-without-raw-metadata-json.md +6 -0
  98. package/corpus/templates/analytics/changelog/2026-07-08-alert-rules-are-easier-to-scan-expand-and-edit-from-settings.md +6 -0
  99. package/corpus/templates/analytics/changelog/2026-07-08-analytics-alert-forms-remember-last-email-recipients.md +6 -0
  100. package/corpus/templates/analytics/changelog/2026-07-08-analytics-alert-rules-can-now-use-per-rule-slack-and-webhook.md +6 -0
  101. package/corpus/templates/analytics/changelog/2026-07-08-dashboard-history-and-chat-context.md +5 -0
  102. package/corpus/templates/analytics/changelog/2026-07-08-dashboard-usage-now-counts-explorer-dashboard-traffic.md +6 -0
  103. package/corpus/templates/analytics/changelog/2026-07-08-demo-mode-session-emails-are-filtered-and-anonymized.md +6 -0
  104. package/corpus/templates/analytics/changelog/2026-07-08-error-issue-detail-adds-stack-traces-and-frequency-bars.md +6 -0
  105. package/corpus/templates/analytics/changelog/2026-07-08-error-issue-detail-now-shows-the-latest-occurrence-message-a.md +6 -0
  106. package/corpus/templates/analytics/changelog/2026-07-08-monitoring-errors-only-show-test-action-when-empty.md +6 -0
  107. package/corpus/templates/analytics/changelog/2026-07-08-production-session-replay-now-requires-private-blob-storage-.md +6 -0
  108. package/corpus/templates/analytics/changelog/2026-07-08-shared-extension-links-now-show-a-clear-message-when-you-do-.md +6 -0
  109. package/corpus/templates/analytics/changelog/2026-07-08-team-settings-show-access-controls-next-to-member-lists.md +6 -0
  110. package/corpus/templates/analytics/changelog/2026-07-08-uptime-checks-no-longer-count-ssrf-setup-time-against-the-re.md +6 -0
  111. package/corpus/templates/analytics/changelog/2026-07-08-uptime-checks-reuse-one-keep-alive-connection-so-recorded-la.md +6 -0
  112. package/corpus/templates/analytics/changelog/2026-07-08-uptime-monitors-now-confirm-transient-timeout-failures-befor.md +6 -0
  113. package/corpus/templates/analytics/changelog/2026-07-08-uptime-monitors-now-use-a-10-second-request-timeout-by-defau.md +6 -0
  114. package/corpus/templates/analytics/docs/uptime-monitoring.md +30 -18
  115. package/corpus/templates/analytics/server/db/schema-monitoring.ts +1 -1
  116. package/corpus/templates/analytics/server/db/schema.ts +56 -0
  117. package/corpus/templates/analytics/server/lib/analytics-alerts.ts +92 -0
  118. package/corpus/templates/analytics/server/lib/dashboards-store.ts +334 -5
  119. package/corpus/templates/analytics/server/lib/error-capture.ts +231 -36
  120. package/corpus/templates/analytics/server/lib/session-replay.ts +114 -8
  121. package/corpus/templates/analytics/server/lib/uptime-monitors.ts +244 -33
  122. package/corpus/templates/analytics/server/plugins/db.ts +112 -2
  123. package/corpus/templates/analytics/server/routes/api/dashboard-agent-context.json.get.ts +1 -0
  124. package/corpus/templates/assets/.agents/skills/actions/SKILL.md +5 -0
  125. package/corpus/templates/assets/.agents/skills/real-time-sync/SKILL.md +1 -1
  126. package/corpus/templates/assets/.agents/skills/security/SKILL.md +7 -0
  127. package/corpus/templates/assets/.agents/skills/storing-data/SKILL.md +5 -1
  128. package/corpus/templates/assets/AGENTS.md +4 -0
  129. package/corpus/templates/assets/app/routes/settings.tsx +1 -1
  130. package/corpus/templates/assets/app/routes/team.tsx +1 -1
  131. package/corpus/templates/brain/.agents/skills/actions/SKILL.md +5 -0
  132. package/corpus/templates/brain/.agents/skills/adding-a-feature/SKILL.md +5 -0
  133. package/corpus/templates/brain/.agents/skills/real-time-sync/SKILL.md +1 -1
  134. package/corpus/templates/brain/.agents/skills/security/SKILL.md +7 -0
  135. package/corpus/templates/brain/AGENTS.md +4 -0
  136. package/corpus/templates/brain/app/routes/team.tsx +1 -1
  137. package/corpus/templates/calendar/.agents/skills/actions/SKILL.md +5 -0
  138. package/corpus/templates/calendar/.agents/skills/real-time-sync/SKILL.md +1 -1
  139. package/corpus/templates/calendar/.agents/skills/security/SKILL.md +7 -0
  140. package/corpus/templates/calendar/.agents/skills/storing-data/SKILL.md +5 -1
  141. package/corpus/templates/calendar/AGENTS.md +4 -0
  142. package/corpus/templates/calendar/app/components/calendar/DayView.tsx +11 -2
  143. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +21 -8
  144. package/corpus/templates/calendar/app/components/calendar/MonthView.tsx +7 -1
  145. package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +11 -2
  146. package/corpus/templates/calendar/app/lib/popover-click-guard.ts +48 -4
  147. package/corpus/templates/calendar/app/pages/Settings.tsx +1 -1
  148. package/corpus/templates/calendar/app/routes/_app.team.tsx +1 -1
  149. package/corpus/templates/calendar/changelog/2026-07-08-clicking-empty-calendar-space-closes-an-open-event-popover-b.md +6 -0
  150. package/corpus/templates/chat/.agents/skills/actions/SKILL.md +5 -0
  151. package/corpus/templates/chat/.agents/skills/adding-a-feature/SKILL.md +5 -0
  152. package/corpus/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
  153. package/corpus/templates/chat/.agents/skills/security/SKILL.md +7 -0
  154. package/corpus/templates/chat/AGENTS.md +4 -0
  155. package/corpus/templates/chat/app/hooks/use-navigation-state.ts +1 -1
  156. package/corpus/templates/chat/app/routes/settings.tsx +2 -2
  157. package/corpus/templates/chat/app/routes/team.tsx +1 -1
  158. package/corpus/templates/clips/.agents/skills/actions/SKILL.md +5 -0
  159. package/corpus/templates/clips/.agents/skills/security/SKILL.md +7 -0
  160. package/corpus/templates/clips/AGENTS.md +4 -0
  161. package/corpus/templates/clips/actions/finalize-recording.ts +9 -3
  162. package/corpus/templates/clips/actions/set-thumbnail.ts +11 -2
  163. package/corpus/templates/clips/app/components/meetings/canvas-editor.tsx +1 -7
  164. package/corpus/templates/clips/app/components/player/player-controls.tsx +21 -13
  165. package/corpus/templates/clips/app/components/player/video-player.tsx +30 -75
  166. package/corpus/templates/clips/app/i18n/ar-SA.ts +6 -5
  167. package/corpus/templates/clips/app/i18n/de-DE.ts +6 -6
  168. package/corpus/templates/clips/app/i18n/en-US.ts +6 -5
  169. package/corpus/templates/clips/app/i18n/es-ES.ts +6 -5
  170. package/corpus/templates/clips/app/i18n/fr-FR.ts +6 -6
  171. package/corpus/templates/clips/app/i18n/hi-IN.ts +6 -5
  172. package/corpus/templates/clips/app/i18n/ja-JP.ts +6 -5
  173. package/corpus/templates/clips/app/i18n/ko-KR.ts +6 -5
  174. package/corpus/templates/clips/app/i18n/pt-BR.ts +6 -5
  175. package/corpus/templates/clips/app/i18n/zh-CN.ts +6 -5
  176. package/corpus/templates/clips/app/i18n/zh-TW.ts +6 -5
  177. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +51 -118
  178. package/corpus/templates/clips/changelog/2026-07-08-hosted-clip-uploads-now-clear-failed-buffered-chunks.md +6 -0
  179. package/corpus/templates/clips/changelog/2026-07-08-hosted-recording-uploads-now-avoid-sql-chunk-storage.md +6 -0
  180. package/corpus/templates/clips/changelog/2026-07-08-meeting-recaps-now-keep-summaries-action-items-and-transcrip.md +6 -0
  181. package/corpus/templates/clips/changelog/2026-07-08-video-playback-controls-now-match-loom-style-5-second-skips-.md +6 -0
  182. package/corpus/templates/clips/server/lib/recording-upload-state.ts +63 -0
  183. package/corpus/templates/clips/server/lib/video-storage.ts +4 -0
  184. package/corpus/templates/clips/server/routes/api/recordings/[recordingId]/thumbnail.post.ts +19 -13
  185. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +40 -1
  186. package/corpus/templates/content/.agents/skills/actions/SKILL.md +5 -0
  187. package/corpus/templates/content/.agents/skills/real-time-sync/SKILL.md +1 -1
  188. package/corpus/templates/content/.agents/skills/security/SKILL.md +7 -0
  189. package/corpus/templates/content/.agents/skills/storing-data/SKILL.md +5 -1
  190. package/corpus/templates/content/AGENTS.md +4 -0
  191. package/corpus/templates/content/app/routes/_app.settings.tsx +2 -2
  192. package/corpus/templates/content/app/routes/_app.team.tsx +1 -1
  193. package/corpus/templates/design/.agents/skills/actions/SKILL.md +5 -0
  194. package/corpus/templates/design/.agents/skills/security/SKILL.md +7 -0
  195. package/corpus/templates/design/AGENTS.md +4 -0
  196. package/corpus/templates/design/actions/take-design-screenshot.ts +12 -9
  197. package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +57 -13
  198. package/corpus/templates/design/app/routes/team.tsx +1 -1
  199. package/corpus/templates/design/changelog/2026-07-08-local-images-added-to-designs-now-upload-to-file-storage-ins.md +6 -0
  200. package/corpus/templates/dispatch/.agents/skills/actions/SKILL.md +5 -0
  201. package/corpus/templates/dispatch/.agents/skills/security/SKILL.md +7 -0
  202. package/corpus/templates/dispatch/AGENTS.md +4 -0
  203. package/corpus/templates/dispatch/app/hooks/use-navigation-state.ts +1 -1
  204. package/corpus/templates/dispatch/app/routes/settings.tsx +2 -2
  205. package/corpus/templates/dispatch/app/routes/team.tsx +1 -1
  206. package/corpus/templates/forms/.agents/skills/actions/SKILL.md +5 -0
  207. package/corpus/templates/forms/.agents/skills/real-time-sync/SKILL.md +1 -1
  208. package/corpus/templates/forms/.agents/skills/security/SKILL.md +7 -0
  209. package/corpus/templates/forms/.agents/skills/storing-data/SKILL.md +5 -1
  210. package/corpus/templates/forms/AGENTS.md +4 -0
  211. package/corpus/templates/forms/app/routes/_app.settings.tsx +2 -2
  212. package/corpus/templates/forms/app/routes/_app.team.tsx +1 -1
  213. package/corpus/templates/forms/shared/navigation.ts +1 -1
  214. package/corpus/templates/macros/.agents/skills/security/SKILL.md +7 -0
  215. package/corpus/templates/macros/AGENTS.md +4 -0
  216. package/corpus/templates/macros/app/routes/settings.tsx +2 -2
  217. package/corpus/templates/macros/app/routes/team.tsx +1 -1
  218. package/corpus/templates/mail/.agents/skills/actions/SKILL.md +5 -0
  219. package/corpus/templates/mail/.agents/skills/email-drafts/SKILL.md +1 -1
  220. package/corpus/templates/mail/.agents/skills/real-time-sync/SKILL.md +1 -1
  221. package/corpus/templates/mail/.agents/skills/security/SKILL.md +7 -0
  222. package/corpus/templates/mail/.agents/skills/storing-data/SKILL.md +5 -1
  223. package/corpus/templates/mail/AGENTS.md +4 -0
  224. package/corpus/templates/mail/changelog/2026-07-08-mail-attachments-in-hosted-environments-now-require-file-sto.md +6 -0
  225. package/corpus/templates/mail/server/handlers/media.ts +26 -1
  226. package/corpus/templates/mail/server/lib/outgoing-email.ts +24 -1
  227. package/corpus/templates/mail/server/lib/upload-store.ts +2 -1
  228. package/corpus/templates/plan/.agents/skills/actions/SKILL.md +5 -0
  229. package/corpus/templates/plan/.agents/skills/adding-a-feature/SKILL.md +5 -0
  230. package/corpus/templates/plan/.agents/skills/real-time-sync/SKILL.md +1 -1
  231. package/corpus/templates/plan/.agents/skills/security/SKILL.md +7 -0
  232. package/corpus/templates/plan/AGENTS.md +4 -0
  233. package/corpus/templates/plan/app/hooks/use-navigation-state.ts +1 -1
  234. package/corpus/templates/plan/app/routes/settings.tsx +2 -2
  235. package/corpus/templates/plan/app/routes/team.tsx +1 -1
  236. package/corpus/templates/plan/changelog/2026-07-08-hosted-plan-images-now-require-connected-storage.md +6 -0
  237. package/corpus/templates/plan/server/lib/plan-assets.ts +33 -4
  238. package/corpus/templates/slides/.agents/skills/actions/SKILL.md +5 -0
  239. package/corpus/templates/slides/.agents/skills/security/SKILL.md +7 -0
  240. package/corpus/templates/slides/AGENTS.md +4 -0
  241. package/corpus/templates/slides/actions/generate-image-api.ts +15 -3
  242. package/corpus/templates/slides/app/routes/settings.tsx +2 -2
  243. package/corpus/templates/slides/app/routes/team.tsx +1 -1
  244. package/corpus/templates/slides/changelog/2026-07-08-generated-slide-images-now-return-hosted-file-storage-urls-i.md +6 -0
  245. package/corpus/templates/slides/shared/api.ts +1 -1
  246. package/dist/application-state/store.d.ts.map +1 -1
  247. package/dist/application-state/store.js +8 -2
  248. package/dist/application-state/store.js.map +1 -1
  249. package/dist/cli/sync-builder-starter-manifest.d.ts.map +1 -1
  250. package/dist/cli/sync-builder-starter-manifest.js +24 -1
  251. package/dist/cli/sync-builder-starter-manifest.js.map +1 -1
  252. package/dist/client/AssistantChat.d.ts.map +1 -1
  253. package/dist/client/AssistantChat.js +24 -13
  254. package/dist/client/AssistantChat.js.map +1 -1
  255. package/dist/client/PoweredByBadge.d.ts +1 -1
  256. package/dist/client/PoweredByBadge.d.ts.map +1 -1
  257. package/dist/client/PoweredByBadge.js +3 -9
  258. package/dist/client/PoweredByBadge.js.map +1 -1
  259. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  260. package/dist/client/agent-chat-adapter.js +28 -9
  261. package/dist/client/agent-chat-adapter.js.map +1 -1
  262. package/dist/client/chat/widgets/DataTableWidget.d.ts.map +1 -1
  263. package/dist/client/chat/widgets/DataTableWidget.js +19 -2
  264. package/dist/client/chat/widgets/DataTableWidget.js.map +1 -1
  265. package/dist/client/db-admin/TableEditor.d.ts.map +1 -1
  266. package/dist/client/db-admin/TableEditor.js +19 -2
  267. package/dist/client/db-admin/TableEditor.js.map +1 -1
  268. package/dist/client/db-admin/export-utils.d.ts +2 -0
  269. package/dist/client/db-admin/export-utils.d.ts.map +1 -1
  270. package/dist/client/db-admin/export-utils.js +11 -3
  271. package/dist/client/db-admin/export-utils.js.map +1 -1
  272. package/dist/client/db-admin/useAgentSync.d.ts.map +1 -1
  273. package/dist/client/db-admin/useAgentSync.js +63 -0
  274. package/dist/client/db-admin/useAgentSync.js.map +1 -1
  275. package/dist/client/error-capture.d.ts.map +1 -1
  276. package/dist/client/error-capture.js +41 -7
  277. package/dist/client/error-capture.js.map +1 -1
  278. package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
  279. package/dist/client/extensions/EmbeddedExtension.js +3 -1
  280. package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
  281. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
  282. package/dist/client/extensions/ExtensionViewer.js +32 -5
  283. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  284. package/dist/client/extensions/InlineExtensionFrame.d.ts.map +1 -1
  285. package/dist/client/extensions/InlineExtensionFrame.js +3 -1
  286. package/dist/client/extensions/InlineExtensionFrame.js.map +1 -1
  287. package/dist/client/extensions/portable-extension.d.ts.map +1 -1
  288. package/dist/client/extensions/portable-extension.js +1 -0
  289. package/dist/client/extensions/portable-extension.js.map +1 -1
  290. package/dist/client/org/OrgSwitcher.d.ts +1 -1
  291. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  292. package/dist/client/org/OrgSwitcher.js +11 -6
  293. package/dist/client/org/OrgSwitcher.js.map +1 -1
  294. package/dist/client/org/TeamPage.d.ts.map +1 -1
  295. package/dist/client/org/TeamPage.js +5 -5
  296. package/dist/client/org/TeamPage.js.map +1 -1
  297. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  298. package/dist/client/settings/SettingsPanel.js +37 -14
  299. package/dist/client/settings/SettingsPanel.js.map +1 -1
  300. package/dist/client/settings/SettingsSection.js +1 -1
  301. package/dist/client/settings/SettingsSection.js.map +1 -1
  302. package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -1
  303. package/dist/client/settings/SettingsTabsPage.js +21 -10
  304. package/dist/client/settings/SettingsTabsPage.js.map +1 -1
  305. package/dist/collab/routes.d.ts +1 -1
  306. package/dist/db-admin/agent-tools.d.ts.map +1 -1
  307. package/dist/db-admin/agent-tools.js +7 -2
  308. package/dist/db-admin/agent-tools.js.map +1 -1
  309. package/dist/db-admin/operations.d.ts.map +1 -1
  310. package/dist/db-admin/operations.js +90 -4
  311. package/dist/db-admin/operations.js.map +1 -1
  312. package/dist/db-admin/routes.d.ts.map +1 -1
  313. package/dist/db-admin/routes.js +1 -0
  314. package/dist/db-admin/routes.js.map +1 -1
  315. package/dist/db-admin/types.d.ts +4 -0
  316. package/dist/db-admin/types.d.ts.map +1 -1
  317. package/dist/db-admin/types.js.map +1 -1
  318. package/dist/extensions/html-shell.d.ts +5 -4
  319. package/dist/extensions/html-shell.d.ts.map +1 -1
  320. package/dist/extensions/html-shell.js.map +1 -1
  321. package/dist/extensions/routes.d.ts.map +1 -1
  322. package/dist/extensions/routes.js +8 -0
  323. package/dist/extensions/routes.js.map +1 -1
  324. package/dist/navigation/index.d.ts +1 -1
  325. package/dist/navigation/index.d.ts.map +1 -1
  326. package/dist/navigation/index.js +1 -1
  327. package/dist/navigation/index.js.map +1 -1
  328. package/dist/notifications/channels.js +1 -17
  329. package/dist/notifications/channels.js.map +1 -1
  330. package/dist/notifications/routes.d.ts +1 -1
  331. package/dist/resources/handlers.d.ts +5 -0
  332. package/dist/resources/handlers.d.ts.map +1 -1
  333. package/dist/resources/handlers.js +9 -8
  334. package/dist/resources/handlers.js.map +1 -1
  335. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  336. package/dist/server/poll.d.ts +12 -4
  337. package/dist/server/poll.d.ts.map +1 -1
  338. package/dist/server/poll.js +236 -9
  339. package/dist/server/poll.js.map +1 -1
  340. package/dist/styles/agent-native.css +27 -0
  341. package/dist/templates/default/.agents/skills/actions/SKILL.md +5 -0
  342. package/dist/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
  343. package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
  344. package/dist/templates/default/.agents/skills/security/SKILL.md +7 -0
  345. package/dist/templates/default/.agents/skills/storing-data/SKILL.md +5 -1
  346. package/dist/templates/default/AGENTS.md +4 -2
  347. package/dist/templates/headless/AGENTS.md +4 -0
  348. package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +5 -0
  349. package/dist/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
  350. package/dist/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +4 -0
  351. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -0
  352. package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +4 -0
  353. package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
  354. package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +7 -0
  355. package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +5 -1
  356. package/dist/templates/workspace-core/AGENTS.md +7 -1
  357. package/dist/templates/workspace-root/AGENTS.md +7 -1
  358. package/package.json +1 -1
  359. package/src/templates/default/.agents/skills/actions/SKILL.md +5 -0
  360. package/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
  361. package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
  362. package/src/templates/default/.agents/skills/security/SKILL.md +7 -0
  363. package/src/templates/default/.agents/skills/storing-data/SKILL.md +5 -1
  364. package/src/templates/default/AGENTS.md +4 -2
  365. package/src/templates/headless/AGENTS.md +4 -0
  366. package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +5 -0
  367. package/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
  368. package/src/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +4 -0
  369. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -0
  370. package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +4 -0
  371. package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
  372. package/src/templates/workspace-core/.agents/skills/security/SKILL.md +7 -0
  373. package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +5 -1
  374. package/src/templates/workspace-core/AGENTS.md +7 -1
  375. package/src/templates/workspace-root/AGENTS.md +7 -1
@@ -312,7 +312,7 @@ const messages = {
312
312
  unassigned: "할당되지 않음",
313
313
  them: "그들을",
314
314
  me: "나",
315
- regeneratingNotes: "메모 재생성 - 자신의 메모가 유지됩니다.",
315
+ regeneratingNotes: "요약 재생성 ",
316
316
  meetingRemoved: "회의가 삭제되었습니다.",
317
317
  couldNotRemoveMeeting: "회의를 삭제할 수 없습니다.",
318
318
  couldNotLoadMeeting: "이 회의를 로드할 수 없습니다.",
@@ -320,8 +320,8 @@ const messages = {
320
320
  couldNotCopyTranscript: "스크립트를 복사할 수 없습니다.",
321
321
  allMeetings: "모든 회의",
322
322
  live: "살다",
323
- generatingNotesInline: "메모 생성 중…",
324
- regenerateNotes: "메모 재생성",
323
+ generatingNotesInline: "요약 생성 중…",
324
+ regenerateNotes: "요약 재생성",
325
325
  share: "공유하다",
326
326
  meetingOptions: "회의 옵션",
327
327
  removeMeeting: "회의 삭제",
@@ -334,12 +334,13 @@ const messages = {
334
334
  desktopHint:
335
335
  "메모를 시작하려면 메뉴 막대에서 Clips Desktop을 열고 Start Meeting Notes를 선택하거나, 알림이 표시되면 Start notes를 클릭하세요. Clips가 마이크와 시스템 오디오를 캡처하고 여기에 기록을 작성합니다.",
336
336
  getDesktopApp: "데스크톱 앱 받기",
337
- generateNotesFailed: "메모를 생성할 수 없습니다. 다시 시도해 보세요.",
337
+ generateNotesFailed: "요약을 생성할 수 없습니다. 다시 시도해 보세요.",
338
338
  attendee_one: "{{count}} 참석자",
339
339
  attendee_other: "{{count}} 참석자",
340
340
  joinCall: "통화에 참여",
341
341
  myNotes: "내 노트",
342
342
  aiNotes: "AI 노트",
343
+ summary: "요약",
343
344
  actionItems: "조치사항",
344
345
  working: "일하고 있는…",
345
346
  noActionItems:
@@ -904,7 +905,7 @@ Clips의 모든 사용자 대상 변경 사항은 여기에 기록됩니다. 명
904
905
  unavailable: "이 회의는 비공개이거나 더 이상 사용할 수 없습니다.",
905
906
  tryClips: "Clips 사용해 보기",
906
907
  attendees: "참석자 {{count}}명",
907
- noAiNotes: "이 회의의 AI 노트가 아직 생성되지 않았습니다.",
908
+ noAiNotes: "이 회의의 요약이 아직 생성되지 않았습니다.",
908
909
  summary: "요약",
909
910
  keyPoints: "핵심 포인트",
910
911
  actionItems: "작업 항목",
@@ -317,7 +317,7 @@ const messages = {
317
317
  unassigned: "Não atribuído",
318
318
  them: "Eles",
319
319
  me: "Meu",
320
- regeneratingNotes: "Regenerando notas — suas próprias notas são mantidas",
320
+ regeneratingNotes: "Regenerando resumo",
321
321
  meetingRemoved: "Reunião removida",
322
322
  couldNotRemoveMeeting: "Não foi possível remover a reunião",
323
323
  couldNotLoadMeeting: "Não foi possível carregar esta reunião.",
@@ -325,8 +325,8 @@ const messages = {
325
325
  couldNotCopyTranscript: "Não foi possível copiar a transcrição",
326
326
  allMeetings: "Todas as reuniões",
327
327
  live: "Ao vivo",
328
- generatingNotesInline: "Gerando notas…",
329
- regenerateNotes: "Regenerar notas",
328
+ generatingNotesInline: "Gerando resumo…",
329
+ regenerateNotes: "Regenerar resumo",
330
330
  share: "Compartilhar",
331
331
  meetingOptions: "Opções de reunião",
332
332
  removeMeeting: "Remover reunião",
@@ -339,12 +339,13 @@ const messages = {
339
339
  desktopHint:
340
340
  "Para iniciar notas, abra o Clips Desktop na barra de menus e escolha Start Meeting Notes, ou clique em Start notes quando o lembrete aparecer. O Clips captura o microfone e o áudio do sistema e escreve a transcrição aqui.",
341
341
  getDesktopApp: "Obtenha o aplicativo para desktop",
342
- generateNotesFailed: "Não foi possível gerar notas. Tente novamente.",
342
+ generateNotesFailed: "Não foi possível gerar o resumo. Tente novamente.",
343
343
  attendee_one: "participante {{count}}",
344
344
  attendee_other: "participantes {{count}}",
345
345
  joinCall: "Participar da chamada",
346
346
  myNotes: "Minhas anotações",
347
347
  aiNotes: "Notas de IA",
348
+ summary: "Resumo",
348
349
  actionItems: "Itens de ação",
349
350
  working: "Trabalhando…",
350
351
  noActionItems:
@@ -921,7 +922,7 @@ Todas as mudanças visíveis para usuários do Clips são documentadas aqui. Voc
921
922
  unavailable: "Esta reunião é privada ou não está mais disponível.",
922
923
  tryClips: "Experimentar Clips",
923
924
  attendees: "{{count}} participantes",
924
- noAiNotes: "As notas de IA ainda não foram geradas para esta reunião.",
925
+ noAiNotes: "Um resumo ainda não foi gerado para esta reunião.",
925
926
  summary: "Resumo",
926
927
  keyPoints: "Pontos principais",
927
928
  actionItems: "Itens de ação",
@@ -299,7 +299,7 @@ const messages = {
299
299
  unassigned: "未分配",
300
300
  them: "他们",
301
301
  me: "我",
302
- regeneratingNotes: "重新生成笔记——保留您自己的笔记",
302
+ regeneratingNotes: "正在重新生成摘要",
303
303
  meetingRemoved: "会议已删除",
304
304
  couldNotRemoveMeeting: "无法删除会议",
305
305
  couldNotLoadMeeting: "无法加载该会议。",
@@ -307,8 +307,8 @@ const messages = {
307
307
  couldNotCopyTranscript: "无法复制成绩单",
308
308
  allMeetings: "所有会议",
309
309
  live: "居住",
310
- generatingNotesInline: "正在生成笔记...",
311
- regenerateNotes: "重新生成笔记",
310
+ generatingNotesInline: "正在生成摘要...",
311
+ regenerateNotes: "重新生成摘要",
312
312
  share: "分享",
313
313
  meetingOptions: "会议选项",
314
314
  removeMeeting: "删除会议",
@@ -321,12 +321,13 @@ const messages = {
321
321
  desktopHint:
322
322
  "要开始记录,请从菜单栏打开 Clips Desktop 并选择 Start Meeting Notes,或在提醒出现时点击 Start notes。Clips 会捕获麦克风和系统音频,并在这里写入文字记录。",
323
323
  getDesktopApp: "获取桌面应用程序",
324
- generateNotesFailed: "无法生成笔记。再试一次。",
324
+ generateNotesFailed: "无法生成摘要。再试一次。",
325
325
  attendee_one: "{{count}} 与会者",
326
326
  attendee_other: "{{count}} 与会者",
327
327
  joinCall: "加入通话",
328
328
  myNotes: "我的笔记",
329
329
  aiNotes: "人工智能笔记",
330
+ summary: "摘要",
330
331
  actionItems: "行动项目",
331
332
  working: "在职的…",
332
333
  noActionItems: "还没有行动项目。从记录生成笔记后,它们会出现在此处。",
@@ -867,7 +868,7 @@ Clips 中所有面向用户的重要更改都会记录在这里。你可以随
867
868
  unavailable: "此会议是私密的或不再可用。",
868
869
  tryClips: "试用 Clips",
869
870
  attendees: "{{count}} 位参会者",
870
- noAiNotes: "此会议尚未生成 AI 笔记。",
871
+ noAiNotes: "此会议尚未生成摘要。",
871
872
  summary: "摘要",
872
873
  keyPoints: "要点",
873
874
  actionItems: "行动项",
@@ -299,7 +299,7 @@ const messages = {
299
299
  unassigned: "未指派",
300
300
  them: "他們",
301
301
  me: "我",
302
- regeneratingNotes: "正在重新產生筆記,並保留您自己的筆記",
302
+ regeneratingNotes: "正在重新產生摘要",
303
303
  meetingRemoved: "會議已刪除",
304
304
  couldNotRemoveMeeting: "無法刪除會議",
305
305
  couldNotLoadMeeting: "無法載入該會議。",
@@ -307,8 +307,8 @@ const messages = {
307
307
  couldNotCopyTranscript: "無法複製逐字稿",
308
308
  allMeetings: "所有會議",
309
309
  live: "即時",
310
- generatingNotesInline: "正在產生筆記...",
311
- regenerateNotes: "重新產生筆記",
310
+ generatingNotesInline: "正在產生摘要...",
311
+ regenerateNotes: "重新產生摘要",
312
312
  share: "分享",
313
313
  meetingOptions: "會議選項",
314
314
  removeMeeting: "刪除會議",
@@ -321,12 +321,13 @@ const messages = {
321
321
  desktopHint:
322
322
  "若要開始筆記,請從選單列開啟 Clips Desktop 並選擇 Start Meeting Notes,或在提醒出現時按 Start notes。Clips 會擷取麥克風和系統音訊,並在這裡寫入逐字稿。",
323
323
  getDesktopApp: "取得桌面應用程式",
324
- generateNotesFailed: "無法產生筆記。請再試一次。",
324
+ generateNotesFailed: "無法產生摘要。請再試一次。",
325
325
  attendee_one: "{{count}} 與會者",
326
326
  attendee_other: "{{count}} 與會者",
327
327
  joinCall: "加入通話",
328
328
  myNotes: "我的筆記",
329
329
  aiNotes: "AI 筆記",
330
+ summary: "摘要",
330
331
  actionItems: "行動項目",
331
332
  working: "處理中…",
332
333
  noActionItems: "還沒有行動項目。從逐字稿產生筆記後,它們會出現在此處。",
@@ -860,7 +861,7 @@ const messages = {
860
861
  unavailable: "此會議是私密的或不再可用。",
861
862
  tryClips: "試用 Clips",
862
863
  attendees: "{{count}} 位與會者",
863
- noAiNotes: "此會議尚未產生 AI 筆記。",
864
+ noAiNotes: "此會議尚未產生摘要。",
864
865
  summary: "摘要",
865
866
  keyPoints: "要點",
866
867
  actionItems: "行動項",
@@ -9,16 +9,16 @@ import {
9
9
  IconClock,
10
10
  IconCopy,
11
11
  IconDeviceDesktop,
12
- IconDots,
12
+ IconDotsVertical,
13
13
  IconEdit,
14
14
  IconExternalLink,
15
15
  IconLoader2,
16
16
  IconNotes,
17
17
  IconPlayerStop,
18
+ IconRefresh,
18
19
  IconShare3,
19
20
  IconTrash,
20
21
  IconUsers,
21
- IconWand,
22
22
  } from "@tabler/icons-react";
23
23
  import { useQueryClient } from "@tanstack/react-query";
24
24
  import { useEffect, useMemo, useRef, useState } from "react";
@@ -60,7 +60,6 @@ import {
60
60
  DropdownMenuTrigger,
61
61
  } from "@/components/ui/dropdown-menu";
62
62
  import { Skeleton } from "@/components/ui/skeleton";
63
- import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
64
63
  import {
65
64
  Tooltip,
66
65
  TooltipContent,
@@ -123,14 +122,6 @@ function formatDateTime(iso?: string | null): string {
123
122
  }
124
123
  }
125
124
 
126
- function formatDurationMs(ms?: number | null): string {
127
- if (!ms || ms <= 0) return "";
128
- const total = Math.round(ms / 1000);
129
- const m = Math.floor(total / 60);
130
- const s = total % 60;
131
- return `${m}:${s.toString().padStart(2, "0")}`;
132
- }
133
-
134
125
  function TitleEditor({
135
126
  value,
136
127
  onChange,
@@ -482,12 +473,6 @@ export default function MeetingDetailRoute() {
482
473
  updateMeeting.mutate({ id: meeting.id, summaryMd: next });
483
474
  };
484
475
 
485
- const handleUserNotesChange = (next: string) => {
486
- if (!meeting) return;
487
- patchCachedMeeting({ userNotesMd: next });
488
- updateMeeting.mutate({ id: meeting.id, userNotesMd: next });
489
- };
490
-
491
476
  const handleToggleActionItem = (index: number, completed: boolean) => {
492
477
  if (!meeting) return;
493
478
  const items = meeting.actionItemsJson ?? [];
@@ -517,7 +502,7 @@ export default function MeetingDetailRoute() {
517
502
 
518
503
  const handleFinalize = () => {
519
504
  if (!meeting) return;
520
- // "My notes" (userNotesMd) is a separate field and is untouched by
505
+ // User-authored notes (userNotesMd) are separate and untouched by
521
506
  // regeneration; only the AI summary/bullets are overwritten. Reassure
522
507
  // the user their own notes are kept.
523
508
  if (hasNotes) {
@@ -626,7 +611,8 @@ export default function MeetingDetailRoute() {
626
611
  const bullets = meeting.bulletsJson ?? [];
627
612
  const actionItems = meeting.actionItemsJson ?? [];
628
613
  const segments = meeting.segmentsJson ?? [];
629
- const recordingDuration = formatDurationMs(meeting.recordingDurationMs);
614
+ const hasSummary =
615
+ !!meeting.summaryMd || bullets.length > 0 || actionItems.length > 0;
630
616
 
631
617
  const handleCopyTranscript = async () => {
632
618
  if (!segments.length) return;
@@ -647,7 +633,7 @@ export default function MeetingDetailRoute() {
647
633
  };
648
634
 
649
635
  return (
650
- <div className="p-6 max-w-6xl mx-auto w-full flex flex-col min-h-0 flex-1">
636
+ <div className="p-6 max-w-6xl mx-auto w-full flex flex-col min-h-0 flex-1 lg:h-full lg:overflow-hidden">
651
637
  <PageHeader>
652
638
  <Tooltip>
653
639
  <TooltipTrigger asChild>
@@ -692,15 +678,6 @@ export default function MeetingDetailRoute() {
692
678
  <IconLoader2 className="h-3.5 w-3.5 animate-spin" />
693
679
  {t("meetingDetail.generatingNotesInline")}
694
680
  </span>
695
- ) : hasNotes ? (
696
- <Button
697
- size="sm"
698
- variant="ghost"
699
- onClick={handleFinalize}
700
- className="cursor-pointer h-8"
701
- >
702
- {t("meetingDetail.regenerateNotes")}
703
- </Button>
704
681
  ) : null}
705
682
  <ShareMeetingPopover
706
683
  meetingId={meeting.id}
@@ -721,10 +698,16 @@ export default function MeetingDetailRoute() {
721
698
  className="h-8 w-8 cursor-pointer"
722
699
  aria-label={t("meetingDetail.meetingOptions")}
723
700
  >
724
- <IconDots className="h-4 w-4" />
701
+ <IconDotsVertical className="h-4 w-4" />
725
702
  </Button>
726
703
  </DropdownMenuTrigger>
727
704
  <DropdownMenuContent align="end" className="w-44">
705
+ {hasSummary && !finalize.isPending && (
706
+ <DropdownMenuItem onSelect={handleFinalize}>
707
+ <IconRefresh className="mr-2 h-4 w-4" />
708
+ {t("meetingDetail.regenerateNotes")}
709
+ </DropdownMenuItem>
710
+ )}
728
711
  {isLive && (
729
712
  <DropdownMenuItem
730
713
  onSelect={(event) => {
@@ -869,94 +852,51 @@ export default function MeetingDetailRoute() {
869
852
  )}
870
853
  </div>
871
854
 
872
- <div className="clips-meeting-detail-grid grid grid-cols-1 gap-6 flex-1 min-h-0">
873
- {/* Two-tone canvas: user notes (black) + AI summary/bullets (gray) */}
855
+ <div className="clips-meeting-detail-grid grid grid-cols-1 gap-6 flex-1 min-h-0 lg:overflow-hidden">
856
+ {/* Summary canvas with generated bullets and action items. */}
874
857
  <div
875
858
  className={cn(
876
859
  "clips-meeting-notes-panel rounded-lg border border-border bg-background min-h-[480px] overflow-hidden flex flex-col",
877
860
  notesJustArrived && "animate-in fade-in duration-500",
878
861
  )}
879
862
  >
880
- <Tabs
881
- defaultValue="notes"
882
- className="flex min-h-0 flex-1 flex-col gap-0"
883
- >
884
- <div className="flex shrink-0 items-center justify-between gap-2 border-b border-border px-3 py-2">
885
- <TabsList className="h-8 gap-1 bg-transparent p-0">
886
- <TabsTrigger
887
- value="notes"
888
- className="h-7 px-2.5 text-xs data-[state=active]:bg-muted"
889
- >
890
- {t("meetingDetail.myNotes")}
891
- </TabsTrigger>
892
- <TabsTrigger
893
- value="ai"
894
- className="h-7 gap-1 px-2.5 text-xs data-[state=active]:bg-muted"
895
- >
896
- <IconWand className="h-3 w-3" />
897
- {t("meetingDetail.aiNotes")}
898
- </TabsTrigger>
899
- <TabsTrigger
900
- value="actions"
901
- className="h-7 px-2.5 text-xs data-[state=active]:bg-muted"
902
- >
903
- {t("meetingDetail.actionItems")}
904
- {actionItems.length > 0 && (
905
- <span className="ml-1 text-muted-foreground">
906
- {actionItems.length}
907
- </span>
908
- )}
909
- </TabsTrigger>
910
- </TabsList>
911
- {finalize.isPending && (
912
- <span className="flex items-center gap-1 text-[10px] text-muted-foreground">
913
- <IconLoader2 className="h-3 w-3 animate-spin" />
914
- {t("meetingDetail.working")}
915
- </span>
916
- )}
863
+ <div className="flex shrink-0 items-center justify-between gap-2 border-b border-border px-4 py-2.5">
864
+ <div className="text-xs font-medium">
865
+ {t("meetingDetail.summary")}
917
866
  </div>
867
+ {finalize.isPending && (
868
+ <span className="flex items-center gap-1 text-[10px] text-muted-foreground">
869
+ <IconLoader2 className="h-3 w-3 animate-spin" />
870
+ {t("meetingDetail.working")}
871
+ </span>
872
+ )}
873
+ </div>
918
874
 
919
- <TabsContent
920
- value="notes"
921
- className="mt-0 min-h-0 flex-1 overflow-y-auto"
922
- >
923
- <CanvasEditor
924
- view="user"
925
- userNotesMd={meeting.userNotesMd ?? ""}
926
- onUserNotesChange={handleUserNotesChange}
927
- readOnly={!canEdit}
928
- />
929
- </TabsContent>
930
-
931
- <TabsContent
932
- value="ai"
933
- className="mt-0 min-h-0 flex-1 overflow-y-auto"
934
- >
935
- <CanvasEditor
936
- view="ai"
937
- summaryMd={meeting.summaryMd ?? ""}
938
- bullets={bullets.map((b) => b.text)}
939
- onSummaryChange={handleSummaryChange}
940
- readOnly={!canEdit}
941
- renderBullet={(b) => (
942
- <BulletLink
943
- bullet={b}
944
- segments={segments}
945
- onJumpTo={handleJumpToSegment}
946
- >
947
- <div className="flex gap-2 text-sm leading-relaxed text-muted-foreground">
948
- <span>•</span>
949
- <span className="flex-1">{b}</span>
950
- </div>
951
- </BulletLink>
952
- )}
953
- />
954
- </TabsContent>
875
+ <div className="min-h-0 flex-1 overflow-y-auto">
876
+ <CanvasEditor
877
+ view="ai"
878
+ summaryMd={meeting.summaryMd ?? ""}
879
+ bullets={bullets.map((b) => b.text)}
880
+ onSummaryChange={handleSummaryChange}
881
+ readOnly={!canEdit}
882
+ renderBullet={(b) => (
883
+ <BulletLink
884
+ bullet={b}
885
+ segments={segments}
886
+ onJumpTo={handleJumpToSegment}
887
+ >
888
+ <div className="flex gap-2 text-sm leading-relaxed text-muted-foreground">
889
+ <span>•</span>
890
+ <span className="flex-1">{b}</span>
891
+ </div>
892
+ </BulletLink>
893
+ )}
894
+ />
955
895
 
956
- <TabsContent
957
- value="actions"
958
- className="mt-0 min-h-0 flex-1 overflow-y-auto px-6 py-4"
959
- >
896
+ <div className="max-w-2xl px-6 pb-6">
897
+ <div className="mb-3 text-xs font-medium">
898
+ {t("meetingDetail.actionItems")}
899
+ </div>
960
900
  {actionItems.length > 0 ? (
961
901
  <ActionItemsByPerson
962
902
  items={actionItems}
@@ -968,8 +908,8 @@ export default function MeetingDetailRoute() {
968
908
  {t("meetingDetail.noActionItems")}
969
909
  </p>
970
910
  )}
971
- </TabsContent>
972
- </Tabs>
911
+ </div>
912
+ </div>
973
913
  </div>
974
914
 
975
915
  {/* Transcript pane — chat-bubble layout */}
@@ -980,13 +920,6 @@ export default function MeetingDetailRoute() {
980
920
  {t("meetingDetail.transcript")}
981
921
  </div>
982
922
  <div className="flex items-center gap-2">
983
- {meeting.transcriptStatus === "ready" && (
984
- <span className="text-[10px] text-muted-foreground">
985
- {t("meetingDetail.segments", {
986
- count: segments.length,
987
- })}
988
- </span>
989
- )}
990
923
  {segments.length > 0 && (
991
924
  <Tooltip>
992
925
  <TooltipTrigger asChild>
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-08
4
+ ---
5
+
6
+ Hosted clip uploads now clear failed buffered chunks and require connected storage before saving thumbnails.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-08
4
+ ---
5
+
6
+ Hosted recording uploads now avoid storing video chunks in SQL and ask users to restart when a resumable storage session is missing.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-08
4
+ ---
5
+
6
+ Meeting recaps now keep summaries, action items, and transcript controls cleaner on one page.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-08
4
+ ---
5
+
6
+ Video playback controls now match Loom-style 5-second skips and pause from the video surface.
@@ -1,5 +1,10 @@
1
1
  import { getDbExec, isPostgres } from "@agent-native/core/db";
2
2
 
3
+ const STALE_CHUNK_PRUNE_LIMIT = 100;
4
+ const STALE_CHUNK_PRUNE_MIN_INTERVAL_MS = 5 * 60 * 1000;
5
+ const DEFAULT_STALE_CHUNK_TTL_MS = 6 * 60 * 60 * 1000;
6
+ const lastPruneByOwner = new Map<string, number>();
7
+
3
8
  function escapeLike(value: string): string {
4
9
  return value.replace(/[!%_]/g, (match) => `!${match}`);
5
10
  }
@@ -8,6 +13,10 @@ function chunkPrefix(recordingId: string): string {
8
13
  return `recording-chunks-${recordingId}-`;
9
14
  }
10
15
 
16
+ function allChunksPrefix(): string {
17
+ return "recording-chunks-";
18
+ }
19
+
11
20
  function likePrefix(prefix: string): string {
12
21
  return `${escapeLike(prefix)}%`;
13
22
  }
@@ -89,6 +98,17 @@ export async function listRecordingChunkKeys(
89
98
  return rows.map((row) => String(row.key));
90
99
  }
91
100
 
101
+ export async function deleteRecordingChunks(
102
+ ownerEmail: string,
103
+ recordingId: string,
104
+ ): Promise<number> {
105
+ const result = await getDbExec().execute({
106
+ sql: `DELETE FROM application_state WHERE session_id = ? AND key LIKE ? ESCAPE '!'`,
107
+ args: [ownerEmail, likePrefix(chunkPrefix(recordingId))],
108
+ });
109
+ return result.rowsAffected ?? 0;
110
+ }
111
+
92
112
  export async function sumRecordingChunkBytes(
93
113
  ownerEmail: string,
94
114
  recordingId: string,
@@ -102,3 +122,46 @@ export async function sumRecordingChunkBytes(
102
122
  });
103
123
  return numberFromRowValue(rows[0]?.bytes);
104
124
  }
125
+
126
+ export async function pruneStaleRecordingChunks(
127
+ ownerEmail: string,
128
+ options: {
129
+ now?: number;
130
+ ttlMs?: number;
131
+ minIntervalMs?: number;
132
+ } = {},
133
+ ): Promise<number> {
134
+ const now = options.now ?? Date.now();
135
+ const minIntervalMs =
136
+ options.minIntervalMs ?? STALE_CHUNK_PRUNE_MIN_INTERVAL_MS;
137
+ const lastPrune = lastPruneByOwner.get(ownerEmail) ?? 0;
138
+ if (minIntervalMs > 0 && now - lastPrune < minIntervalMs) return 0;
139
+ lastPruneByOwner.set(ownerEmail, now);
140
+
141
+ const ttlMs = options.ttlMs ?? DEFAULT_STALE_CHUNK_TTL_MS;
142
+ const cutoff = new Date(now - ttlMs).toISOString();
143
+ const createdAtExpression = isPostgres()
144
+ ? `value::jsonb ->> 'createdAt'`
145
+ : `json_extract(value, '$.createdAt')`;
146
+ const { rows } = await getDbExec().execute({
147
+ sql: `SELECT key FROM application_state WHERE session_id = ? AND key LIKE ? ESCAPE '!' AND ${createdAtExpression} IS NOT NULL AND ${createdAtExpression} < ? LIMIT ?`,
148
+ args: [
149
+ ownerEmail,
150
+ likePrefix(allChunksPrefix()),
151
+ cutoff,
152
+ STALE_CHUNK_PRUNE_LIMIT,
153
+ ],
154
+ });
155
+
156
+ let purged = 0;
157
+ for (const row of rows) {
158
+ const key = String(row.key ?? "");
159
+ if (!key) continue;
160
+ const result = await getDbExec().execute({
161
+ sql: `DELETE FROM application_state WHERE session_id = ? AND key = ?`,
162
+ args: [ownerEmail, key],
163
+ });
164
+ purged += result.rowsAffected ?? 0;
165
+ }
166
+ return purged;
167
+ }
@@ -25,6 +25,10 @@ export function requiresConfiguredVideoStorage(): boolean {
25
25
  return process.env.NODE_ENV === "production" || !isLikelyLocalDatabase();
26
26
  }
27
27
 
28
+ export function allowsSqlRecordingChunkScratch(): boolean {
29
+ return !requiresConfiguredVideoStorage();
30
+ }
31
+
28
32
  interface VideoStorageResolveContext {
29
33
  userEmail?: string;
30
34
  orgId?: string | null;
@@ -28,6 +28,10 @@ import {
28
28
  getEventOwnerContext,
29
29
  ownerEmailMatches,
30
30
  } from "../../../../lib/recordings.js";
31
+ import {
32
+ requiresConfiguredVideoStorage,
33
+ STORAGE_SETUP_REQUIRED_REASON,
34
+ } from "../../../../lib/video-storage.js";
31
35
 
32
36
  const MAX_THUMBNAIL_BYTES = 2 * 1024 * 1024;
33
37
 
@@ -154,12 +158,9 @@ export default defineEventHandler(async (event: H3Event) => {
154
158
  return { error: "Thumbnail bytes do not match Content-Type" };
155
159
  }
156
160
 
157
- // Try the configured file-upload provider first (Builder.io or a
158
- // user-registered one). In dev / solo mode no provider is usually
159
- // configured and `uploadFile()` returns `null` in that case we fall
160
- // back to a base64 `data:` URL inline in the `recordings.thumbnail_url`
161
- // column. It's not glamorous but it unblocks the library grid
162
- // immediately and mirrors what `set-thumbnail` does.
161
+ // Try the configured file-upload provider first. Hosted/persistent SQL
162
+ // must not store base64 data URLs in recordings.thumbnail_url; local dev can
163
+ // still fall back inline to keep the first-frame preview flow lightweight.
163
164
  const uploaded = await uploadFile({
164
165
  data: bytes,
165
166
  mimeType,
@@ -177,15 +178,20 @@ export default defineEventHandler(async (event: H3Event) => {
177
178
  bytes: bytes.byteLength,
178
179
  });
179
180
  } else {
181
+ if (requiresConfiguredVideoStorage()) {
182
+ setResponseStatus(event, 409);
183
+ return {
184
+ ok: false,
185
+ error: STORAGE_SETUP_REQUIRED_REASON,
186
+ storageSetupRequired: true,
187
+ };
188
+ }
180
189
  const base64 = Buffer.from(bytes).toString("base64");
181
190
  url = `data:${mimeType};base64,${base64}`;
182
- console.log(
183
- "[thumbnail] no provider configured, stored inline data URL",
184
- {
185
- recordingId,
186
- bytes: bytes.byteLength,
187
- },
188
- );
191
+ console.log("[thumbnail] local storage fallback stored inline data URL", {
192
+ recordingId,
193
+ bytes: bytes.byteLength,
194
+ });
189
195
  }
190
196
 
191
197
  await db