@agent-native/core 0.137.8 → 0.139.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 (472) hide show
  1. package/agent-native.eject.json +2 -0
  2. package/corpus/README.md +1 -1
  3. package/corpus/templates/analytics/.agents/skills/agent-native-docs/SKILL.md +23 -3
  4. package/corpus/templates/analytics/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  5. package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +15 -0
  6. package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +23 -2
  7. package/corpus/templates/analytics/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  8. package/corpus/templates/analytics/AGENTS.md +2 -2
  9. package/corpus/templates/analytics/actions/get-first-party-analytics-health.ts +65 -0
  10. package/corpus/templates/analytics/actions/provider-api-catalog.ts +3 -6
  11. package/corpus/templates/analytics/actions/provider-api-docs.ts +3 -6
  12. package/corpus/templates/analytics/actions/provider-api-request.ts +3 -6
  13. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +3 -3
  14. package/corpus/templates/analytics/agent-native.json +12 -0
  15. package/corpus/templates/analytics/app/i18n-data.ts +162 -0
  16. package/corpus/templates/analytics/app/pages/DataSources.tsx +126 -1
  17. package/corpus/templates/analytics/changelog/2026-08-05-analytics-now-flags-neon-pressure-and-guides-high-volume-tra.md +6 -0
  18. package/corpus/templates/analytics/changelog/2026-08-05-first-party-analytics-uses-compact-rollups-for-faster-usage-.md +6 -0
  19. package/corpus/templates/analytics/server/db/schema.ts +52 -0
  20. package/corpus/templates/analytics/server/lib/credential-keys.ts +3 -0
  21. package/corpus/templates/analytics/server/lib/dashboard-report.ts +2 -0
  22. package/corpus/templates/analytics/server/lib/emails.ts +51 -0
  23. package/corpus/templates/analytics/server/lib/first-party-analytics-health.ts +397 -0
  24. package/corpus/templates/analytics/server/lib/first-party-analytics-rollups.ts +182 -0
  25. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +86 -15
  26. package/corpus/templates/analytics/server/lib/provider-api.ts +20 -1
  27. package/corpus/templates/analytics/server/lib/replay-storage.ts +1 -1
  28. package/corpus/templates/analytics/server/plugins/agent-chat.ts +1 -0
  29. package/corpus/templates/analytics/server/plugins/db.ts +60 -0
  30. package/corpus/templates/analytics/server/plugins/transactional-emails.ts +5 -0
  31. package/corpus/templates/assets/.agents/skills/agent-native-docs/SKILL.md +23 -3
  32. package/corpus/templates/assets/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  33. package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +23 -2
  34. package/corpus/templates/assets/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  35. package/corpus/templates/assets/agent-native.json +12 -0
  36. package/corpus/templates/assets/server/lib/generation.ts +8 -8
  37. package/corpus/templates/assets/server/lib/storage.ts +1 -1
  38. package/corpus/templates/assets/server/plugins/onboarding.ts +1 -1
  39. package/corpus/templates/brain/.agents/skills/agent-native-docs/SKILL.md +23 -3
  40. package/corpus/templates/brain/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  41. package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +23 -2
  42. package/corpus/templates/brain/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  43. package/corpus/templates/brain/agent-native.json +12 -0
  44. package/corpus/templates/calendar/.agents/skills/agent-native-docs/SKILL.md +23 -3
  45. package/corpus/templates/calendar/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  46. package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +23 -2
  47. package/corpus/templates/calendar/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  48. package/corpus/templates/calendar/agent-native.json +12 -0
  49. package/corpus/templates/calendar/server/lib/booking-emails.ts +154 -70
  50. package/corpus/templates/calendar/server/lib/emails.ts +167 -0
  51. package/corpus/templates/calendar/server/lib/event-guest-notifications.ts +64 -28
  52. package/corpus/templates/calendar/server/plugins/transactional-emails.ts +5 -0
  53. package/corpus/templates/chat/.agents/skills/agent-native-docs/SKILL.md +23 -3
  54. package/corpus/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  55. package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +23 -2
  56. package/corpus/templates/chat/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  57. package/corpus/templates/chat/AGENTS.md +3 -0
  58. package/corpus/templates/chat/DESIGN.md +28 -0
  59. package/corpus/templates/chat/agent-native.json +12 -0
  60. package/corpus/templates/clips/.agents/skills/agent-native-docs/SKILL.md +23 -3
  61. package/corpus/templates/clips/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  62. package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +23 -2
  63. package/corpus/templates/clips/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  64. package/corpus/templates/clips/actions/cleanup-transcript.ts +2 -2
  65. package/corpus/templates/clips/actions/delete-recording-permanent.ts +3 -0
  66. package/corpus/templates/clips/actions/get-playback-position.ts +68 -0
  67. package/corpus/templates/clips/actions/import-loom-recording.ts +2 -2
  68. package/corpus/templates/clips/actions/invite-member.ts +39 -15
  69. package/corpus/templates/clips/actions/save-playback-position.ts +80 -0
  70. package/corpus/templates/clips/actions/set-thumbnail.ts +1 -1
  71. package/corpus/templates/clips/agent-native.json +12 -0
  72. package/corpus/templates/clips/app/components/player/video-player.tsx +54 -5
  73. package/corpus/templates/clips/app/hooks/use-playback-position.ts +188 -0
  74. package/corpus/templates/clips/app/hooks/use-view-tracking.ts +6 -24
  75. package/corpus/templates/clips/app/lib/playback-position.ts +99 -0
  76. package/corpus/templates/clips/app/lib/viewer-session.ts +29 -0
  77. package/corpus/templates/clips/changelog/2026-08-05-clip-buffering-now-uses-buffering-copy-after-playback.md +6 -0
  78. package/corpus/templates/clips/changelog/2026-08-05-clips-remembers-your-playback-position-when-you-reopen-a-cli.md +6 -0
  79. package/corpus/templates/clips/learnings.defaults.md +1 -1
  80. package/corpus/templates/clips/server/db/schema.ts +18 -0
  81. package/corpus/templates/clips/server/lib/emails.ts +256 -0
  82. package/corpus/templates/clips/server/lib/public-agent-context.ts +1 -1
  83. package/corpus/templates/clips/server/lib/transactional-email-templates.ts +24 -0
  84. package/corpus/templates/clips/server/lib/video-storage.ts +1 -1
  85. package/corpus/templates/clips/server/plugins/db.ts +15 -0
  86. package/corpus/templates/clips/server/plugins/transactional-email-catalog.ts +5 -0
  87. package/corpus/templates/clips/server/routes/api/media/index.post.ts +1 -1
  88. package/corpus/templates/content/.agents/skills/agent-native-docs/SKILL.md +23 -3
  89. package/corpus/templates/content/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  90. package/corpus/templates/content/.agents/skills/document-editing/references/databases.md +13 -0
  91. package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +23 -2
  92. package/corpus/templates/content/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  93. package/corpus/templates/content/AGENTS.md +1 -0
  94. package/corpus/templates/content/actions/_content-database-mutation-lock.ts +41 -0
  95. package/corpus/templates/content/actions/_content-database-row-migration.ts +569 -0
  96. package/corpus/templates/content/actions/_database-source-utils.ts +82 -36
  97. package/corpus/templates/content/actions/_database-utils.ts +5 -0
  98. package/corpus/templates/content/actions/_delete-content-space.ts +25 -11
  99. package/corpus/templates/content/actions/add-database-item.ts +60 -42
  100. package/corpus/templates/content/actions/attach-content-database-source.ts +2 -0
  101. package/corpus/templates/content/actions/configure-document-property.ts +99 -104
  102. package/corpus/templates/content/actions/delete-content-database.ts +19 -7
  103. package/corpus/templates/content/actions/delete-document-property.ts +47 -58
  104. package/corpus/templates/content/actions/delete-document.ts +390 -167
  105. package/corpus/templates/content/actions/disconnect-content-database-source.ts +41 -24
  106. package/corpus/templates/content/actions/duplicate-database-item.ts +63 -31
  107. package/corpus/templates/content/actions/duplicate-database-items.ts +86 -43
  108. package/corpus/templates/content/actions/duplicate-document-property.ts +37 -14
  109. package/corpus/templates/content/actions/migrate-content-database-rows.ts +830 -0
  110. package/corpus/templates/content/actions/move-database-item.ts +14 -0
  111. package/corpus/templates/content/actions/permanently-delete-document.ts +27 -6
  112. package/corpus/templates/content/actions/remove-database-items.ts +13 -0
  113. package/corpus/templates/content/actions/reorder-document-property.ts +45 -46
  114. package/corpus/templates/content/actions/set-document-property.ts +68 -28
  115. package/corpus/templates/content/actions/submit-content-database-form.ts +49 -0
  116. package/corpus/templates/content/actions/transcribe-media.ts +1 -1
  117. package/corpus/templates/content/agent-native.json +12 -0
  118. package/corpus/templates/content/app/components/editor/image-upload.ts +2 -2
  119. package/corpus/templates/content/app/i18n-data.ts +1 -1
  120. package/corpus/templates/content/changelog/2026-08-01-content-can-reorganize-every-row-in-an-existing-database-as-.md +6 -0
  121. package/corpus/templates/content/parity/matrix.md +1 -1
  122. package/corpus/templates/content/parity/matrix.ts +4 -2
  123. package/corpus/templates/content/server/db/schema.ts +30 -0
  124. package/corpus/templates/content/server/lib/comment-notifications.ts +57 -26
  125. package/corpus/templates/content/server/lib/emails.ts +70 -0
  126. package/corpus/templates/content/server/plugins/db.ts +24 -0
  127. package/corpus/templates/content/server/plugins/onboarding.ts +2 -2
  128. package/corpus/templates/content/server/plugins/transactional-emails.ts +5 -0
  129. package/corpus/templates/crm/.agents/skills/agent-native-docs/SKILL.md +23 -3
  130. package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  131. package/corpus/templates/crm/agent-native.json +12 -0
  132. package/corpus/templates/design/.agents/skills/agent-native-docs/SKILL.md +23 -3
  133. package/corpus/templates/design/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  134. package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +23 -2
  135. package/corpus/templates/design/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  136. package/corpus/templates/design/CODE_NATIVE_DESIGN_STUDIO_IMPLEMENTATION_PLAN.md +2 -2
  137. package/corpus/templates/design/DESIGN-STUDIO-PLAN.md +2 -2
  138. package/corpus/templates/design/actions/apply-design-token-edit.ts +1 -1
  139. package/corpus/templates/design/actions/capture-design-state.ts +1 -1
  140. package/corpus/templates/design/actions/connect-builder-app.ts +2 -2
  141. package/corpus/templates/design/actions/create-design-branch.ts +1 -1
  142. package/corpus/templates/design/actions/create-fusion-app.ts +3 -3
  143. package/corpus/templates/design/actions/deploy-design-preview.ts +1 -1
  144. package/corpus/templates/design/actions/get-component-details.ts +1 -1
  145. package/corpus/templates/design/actions/get-design-branch-diff.ts +1 -1
  146. package/corpus/templates/design/actions/index-components.ts +3 -3
  147. package/corpus/templates/design/actions/index-design-system-with-builder.ts +1 -1
  148. package/corpus/templates/design/actions/migrate-inline-design-to-app.ts +3 -3
  149. package/corpus/templates/design/actions/open-component-source.ts +1 -1
  150. package/corpus/templates/design/actions/update-design.ts +61 -0
  151. package/corpus/templates/design/agent-native.json +12 -0
  152. package/corpus/templates/design/app/components/design/edit-panel/component-section.tsx +1 -1
  153. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +1 -1
  154. package/corpus/templates/design/scripts/qa-figma-stress-import.ts +1 -1
  155. package/corpus/templates/design/server/lib/figma-node-import.ts +1 -1
  156. package/corpus/templates/design/shared/design-source-capabilities.ts +25 -9
  157. package/corpus/templates/dispatch/.agents/skills/agent-native-docs/SKILL.md +23 -3
  158. package/corpus/templates/dispatch/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  159. package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +23 -2
  160. package/corpus/templates/dispatch/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  161. package/corpus/templates/dispatch/agent-native.json +12 -0
  162. package/corpus/templates/dispatch/app/routes/transactional-email.$appId.$id.tsx +4 -0
  163. package/corpus/templates/dispatch/app/routes/transactional-email.tsx +4 -0
  164. package/corpus/templates/factory/.agents/skills/agent-native-docs/SKILL.md +23 -3
  165. package/corpus/templates/factory/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  166. package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +23 -2
  167. package/corpus/templates/factory/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  168. package/corpus/templates/factory/agent-native.json +12 -0
  169. package/corpus/templates/forms/.agents/skills/agent-native-docs/SKILL.md +23 -3
  170. package/corpus/templates/forms/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  171. package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +23 -2
  172. package/corpus/templates/forms/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  173. package/corpus/templates/forms/actions/export-responses.ts +1 -1
  174. package/corpus/templates/forms/agent-native.json +12 -0
  175. package/corpus/templates/forms/server/lib/emails.ts +52 -0
  176. package/corpus/templates/forms/server/lib/response-email.ts +2 -0
  177. package/corpus/templates/forms/server/plugins/transactional-emails.ts +5 -0
  178. package/corpus/templates/macros/.agents/skills/agent-native-docs/SKILL.md +23 -3
  179. package/corpus/templates/macros/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  180. package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +23 -2
  181. package/corpus/templates/macros/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  182. package/corpus/templates/macros/agent-native.json +12 -0
  183. package/corpus/templates/mail/.agents/skills/agent-native-docs/SKILL.md +23 -3
  184. package/corpus/templates/mail/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  185. package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +23 -2
  186. package/corpus/templates/mail/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  187. package/corpus/templates/mail/agent-native.json +12 -0
  188. package/corpus/templates/mail/app/i18n/en-US.ts +1 -1
  189. package/corpus/templates/mail/server/lib/media-upload.ts +1 -1
  190. package/corpus/templates/plan/.agents/skills/agent-native-docs/SKILL.md +23 -3
  191. package/corpus/templates/plan/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  192. package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +23 -2
  193. package/corpus/templates/plan/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  194. package/corpus/templates/plan/actions/request-plan-access.ts +33 -12
  195. package/corpus/templates/plan/agent-native.json +12 -0
  196. package/corpus/templates/plan/server/lib/comment-notifications.ts +53 -27
  197. package/corpus/templates/plan/server/lib/emails.ts +67 -0
  198. package/corpus/templates/plan/server/lib/plan-assets.ts +1 -1
  199. package/corpus/templates/plan/server/plugins/transactional-emails.ts +5 -0
  200. package/corpus/templates/slides/.agents/skills/agent-native-docs/SKILL.md +23 -3
  201. package/corpus/templates/slides/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  202. package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +23 -2
  203. package/corpus/templates/slides/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  204. package/corpus/templates/slides/actions/generate-image-api.ts +1 -1
  205. package/corpus/templates/slides/actions/generate-slides-ai.ts +1 -1
  206. package/corpus/templates/slides/actions/import-file.ts +2 -2
  207. package/corpus/templates/slides/actions/index-design-system-with-builder.ts +1 -1
  208. package/corpus/templates/slides/agent-native.json +12 -0
  209. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +1 -1
  210. package/corpus/templates/slides/app/i18n/en-US.ts +2 -2
  211. package/corpus/templates/slides/app/lib/deck-sorting.ts +19 -0
  212. package/corpus/templates/slides/app/lib/image-drop-to-agent.ts +1 -1
  213. package/corpus/templates/slides/app/pages/Index.tsx +7 -2
  214. package/corpus/templates/slides/changelog/2026-08-05-decks-are-now-sorted-by-most-recently-updated.md +6 -0
  215. package/corpus/templates/slides/server/handlers/assets.ts +1 -1
  216. package/corpus/templates/slides/server/handlers/uploads.ts +1 -1
  217. package/corpus/templates/slides/server/lib/comment-notifications.ts +44 -21
  218. package/corpus/templates/slides/server/lib/emails.ts +40 -0
  219. package/corpus/templates/slides/server/plugins/transactional-emails.ts +5 -0
  220. package/corpus/templates/tasks/.agents/skills/agent-native-docs/SKILL.md +23 -3
  221. package/corpus/templates/tasks/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  222. package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +23 -2
  223. package/corpus/templates/tasks/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  224. package/corpus/templates/tasks/agent-native.json +12 -0
  225. package/dist/action.d.ts +6 -0
  226. package/dist/agent/engine/builder-engine.js +2 -2
  227. package/dist/agent/engine/credential-errors.d.ts +1 -1
  228. package/dist/agent/engine/credential-errors.js +2 -2
  229. package/dist/agent/production-agent.js +3 -2
  230. package/dist/brand-kit/fig/index.js +1 -1
  231. package/dist/cli/agent.js +45 -3
  232. package/dist/cli/code-agent-executor.js +2 -1
  233. package/dist/cli/create.d.ts +9 -1
  234. package/dist/cli/create.js +94 -1
  235. package/dist/cli/doctor.d.ts +8 -11
  236. package/dist/cli/doctor.js +92 -24
  237. package/dist/cli/index.js +6 -5
  238. package/dist/client/AgentAskPopover.d.ts +3 -1
  239. package/dist/client/AgentAskPopover.js +2 -2
  240. package/dist/client/AgentPanel.js +9 -3
  241. package/dist/client/AssistantChat.js +54 -33
  242. package/dist/client/MultiTabAssistantChat.js +1 -1
  243. package/dist/client/RouteTransitionIndicator.d.ts +7 -0
  244. package/dist/client/RouteTransitionIndicator.js +31 -0
  245. package/dist/client/agent-engine-key.js +1 -1
  246. package/dist/client/app-providers.js +11 -2
  247. package/dist/client/chat/message-components.js +1 -1
  248. package/dist/client/chat/run-recovery.js +1 -1
  249. package/dist/client/chat/tool-call-display.d.ts +3 -1
  250. package/dist/client/chat/tool-call-display.js +4 -3
  251. package/dist/client/chat-model-groups.d.ts +6 -0
  252. package/dist/client/chat-model-groups.js +11 -0
  253. package/dist/client/error-format.js +1 -1
  254. package/dist/client/i18n.js +1 -1
  255. package/dist/client/onboarding/FirstRunOnboarding.d.ts +5 -1
  256. package/dist/client/onboarding/FirstRunOnboarding.js +29 -13
  257. package/dist/client/onboarding/first-run-enabled.d.ts +6 -1
  258. package/dist/client/onboarding/first-run-enabled.js +33 -3
  259. package/dist/client/onboarding/use-onboarding.js +16 -11
  260. package/dist/client/resources/mcp-integration-catalog.js +26 -0
  261. package/dist/client/resources/mcp-integration-logos.js +4 -0
  262. package/dist/client/route-warmup.js +56 -10
  263. package/dist/client/settings/AccountSettingsCard.js +78 -3
  264. package/dist/client/settings/SettingsPanel.js +1 -1
  265. package/dist/client/settings/VoiceTranscriptionSection.js +2 -2
  266. package/dist/client/settings/useBuilderStatus.js +1 -1
  267. package/dist/client/setup-connections/useBuilderConnectCardController.js +1 -1
  268. package/dist/client/ui/index.d.ts +1 -0
  269. package/dist/client/ui/index.js +1 -0
  270. package/dist/client/uploads/upload-editor-image.js +1 -1
  271. package/dist/client/use-chat-threads.js +3 -0
  272. package/dist/collab/routes.d.ts +1 -1
  273. package/dist/config.d.ts +48 -0
  274. package/dist/config.js +111 -0
  275. package/dist/db/migrations.js +5 -0
  276. package/dist/eject/provider-api-definitions.d.ts +1 -1
  277. package/dist/eject/provider-api-definitions.js +1 -0
  278. package/dist/eject/remote-mcp-presets.js +1 -0
  279. package/dist/email-catalog/actions/list-email-activity.d.ts +6 -0
  280. package/dist/email-catalog/actions/list-email-activity.js +15 -0
  281. package/dist/email-catalog/actions/list-email-engagement.d.ts +6 -0
  282. package/dist/email-catalog/actions/list-email-engagement.js +15 -0
  283. package/dist/email-catalog/actions/list-email-log.d.ts +8 -0
  284. package/dist/email-catalog/actions/list-email-log.js +22 -0
  285. package/dist/email-catalog/actions/list-transactional-emails.d.ts +23 -0
  286. package/dist/email-catalog/actions/list-transactional-emails.js +61 -0
  287. package/dist/email-catalog/actions/render-transactional-email-preview.d.ts +10 -0
  288. package/dist/email-catalog/actions/render-transactional-email-preview.js +24 -0
  289. package/dist/email-catalog/authorize.d.ts +2 -0
  290. package/dist/email-catalog/authorize.js +10 -0
  291. package/dist/email-catalog/log.d.ts +57 -0
  292. package/dist/email-catalog/log.js +117 -0
  293. package/dist/email-catalog/provider-metrics.d.ts +34 -0
  294. package/dist/email-catalog/provider-metrics.js +165 -0
  295. package/dist/email-catalog/registry.d.ts +79 -0
  296. package/dist/email-catalog/registry.js +71 -0
  297. package/dist/email-catalog/schema.d.ts +212 -0
  298. package/dist/email-catalog/schema.js +49 -0
  299. package/dist/email-catalog/system-emails.d.ts +14 -0
  300. package/dist/email-catalog/system-emails.js +68 -0
  301. package/dist/extensions/web-search-tool.js +2 -2
  302. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  303. package/dist/file-upload/actions/upload-image.js +1 -1
  304. package/dist/file-upload/registry.js +1 -1
  305. package/dist/guards/index.d.ts +3 -0
  306. package/dist/guards/index.js +2 -0
  307. package/dist/guards/no-empty-migrations.d.ts +14 -0
  308. package/dist/guards/no-empty-migrations.js +126 -0
  309. package/dist/index.browser.d.ts +1 -0
  310. package/dist/index.browser.js +3 -0
  311. package/dist/index.d.ts +1 -0
  312. package/dist/index.js +1 -0
  313. package/dist/localization/default-messages.d.ts +69 -0
  314. package/dist/localization/default-messages.js +71 -2
  315. package/dist/notifications/routes.d.ts +2 -2
  316. package/dist/onboarding/app-profile.js +1 -1
  317. package/dist/onboarding/plugin.d.ts +2 -0
  318. package/dist/onboarding/plugin.js +29 -2
  319. package/dist/org/handlers.js +8 -1
  320. package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
  321. package/dist/provider-api/actions/provider-api.d.ts +13 -13
  322. package/dist/provider-api/index.d.ts +4 -4
  323. package/dist/provider-api/index.js +35 -0
  324. package/dist/resources/handlers.d.ts +1 -1
  325. package/dist/resources/handlers.js +1 -1
  326. package/dist/scripts/docs/framework-search.d.ts +9 -0
  327. package/dist/scripts/docs/framework-search.js +239 -0
  328. package/dist/scripts/docs/index.js +1 -0
  329. package/dist/scripts/docs/search.d.ts +10 -0
  330. package/dist/scripts/docs/search.js +1 -1
  331. package/dist/scripts/docs/source-search.d.ts +10 -2
  332. package/dist/scripts/docs/source-search.js +108 -41
  333. package/dist/search-utils/index.d.ts +11 -0
  334. package/dist/search-utils/index.js +72 -0
  335. package/dist/server/action-change.d.ts +6 -0
  336. package/dist/server/action-change.js +28 -14
  337. package/dist/server/action-discovery.js +31 -0
  338. package/dist/server/action-routes.js +1 -0
  339. package/dist/server/agent-chat/browser-team-tools.js +1 -1
  340. package/dist/server/agent-chat/script-entries.js +43 -2
  341. package/dist/server/auth-login-mode.d.ts +8 -0
  342. package/dist/server/auth-login-mode.js +17 -0
  343. package/dist/server/auth.js +100 -15
  344. package/dist/server/better-auth-instance.d.ts +36 -0
  345. package/dist/server/better-auth-instance.js +42 -5
  346. package/dist/server/builder-design-systems.js +1 -1
  347. package/dist/server/core-routes-plugin.js +17 -14
  348. package/dist/server/credential-provider.js +3 -3
  349. package/dist/server/email-templates.d.ts +7 -0
  350. package/dist/server/email-templates.js +24 -0
  351. package/dist/server/email.d.ts +26 -0
  352. package/dist/server/email.js +66 -4
  353. package/dist/server/framework-request-handler.js +6 -0
  354. package/dist/server/index.d.ts +1 -0
  355. package/dist/server/index.js +1 -0
  356. package/dist/server/onboarding-html.d.ts +2 -0
  357. package/dist/server/onboarding-html.js +169 -8
  358. package/dist/server/realtime-token.d.ts +1 -1
  359. package/dist/server/realtime-voice.js +1 -1
  360. package/dist/server/sentry.d.ts +1 -1
  361. package/dist/server/transcribe-voice.js +3 -3
  362. package/dist/shared/first-run-onboarding.d.ts +1 -0
  363. package/dist/shared/first-run-onboarding.js +1 -0
  364. package/dist/templates/chat/.agents/skills/agent-native-docs/SKILL.md +23 -3
  365. package/dist/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  366. package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +23 -2
  367. package/dist/templates/chat/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  368. package/dist/templates/chat/AGENTS.md +3 -0
  369. package/dist/templates/chat/DESIGN.md +28 -0
  370. package/dist/templates/chat/agent-native.json +12 -0
  371. package/dist/templates/default/.agents/skills/agent-native-docs/SKILL.md +23 -3
  372. package/dist/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  373. package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +23 -2
  374. package/dist/templates/default/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  375. package/dist/templates/default/AGENTS.md +4 -0
  376. package/dist/templates/default/DESIGN.md +30 -0
  377. package/dist/templates/default/agent-native.json +9 -0
  378. package/dist/templates/default/app/i18n/ar-SA.ts +2 -2
  379. package/dist/templates/default/app/i18n/de-DE.ts +2 -2
  380. package/dist/templates/default/app/i18n/en-US.ts +2 -2
  381. package/dist/templates/default/app/i18n/es-ES.ts +2 -2
  382. package/dist/templates/default/app/i18n/fr-FR.ts +2 -2
  383. package/dist/templates/default/app/i18n/hi-IN.ts +2 -2
  384. package/dist/templates/default/app/i18n/ja-JP.ts +2 -2
  385. package/dist/templates/default/app/i18n/ko-KR.ts +2 -2
  386. package/dist/templates/default/app/i18n/pt-BR.ts +2 -2
  387. package/dist/templates/default/app/i18n/zh-CN.ts +2 -2
  388. package/dist/templates/default/app/i18n/zh-TW.ts +1 -1
  389. package/dist/templates/default/package.json +1 -0
  390. package/dist/templates/headless/.agents/skills/agent-native-docs/SKILL.md +23 -3
  391. package/dist/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  392. package/dist/templates/headless/agent-native.json +9 -0
  393. package/dist/templates/headless/package.json +2 -0
  394. package/dist/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +23 -3
  395. package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  396. package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +23 -2
  397. package/dist/templates/workspace-core/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  398. package/dist/templates/workspace-core/AGENTS.md +3 -0
  399. package/dist/templates/workspace-core/DESIGN.md +35 -0
  400. package/dist/templates/workspace-root/AGENTS.md +3 -0
  401. package/dist/templates/workspace-root/DESIGN.md +35 -0
  402. package/dist/templates/workspace-root/agent-native.json +9 -0
  403. package/dist/templates/workspace-root/package.json +3 -0
  404. package/dist/transcription/builder-transcription.js +1 -1
  405. package/dist/user-profile/actions/change-password.d.ts +8 -0
  406. package/dist/user-profile/actions/change-password.js +24 -0
  407. package/dist/user-profile/actions/get-auth-methods.d.ts +6 -0
  408. package/dist/user-profile/actions/get-auth-methods.js +23 -0
  409. package/dist/user-profile/actions/set-password.d.ts +7 -0
  410. package/dist/user-profile/actions/set-password.js +23 -0
  411. package/dist/vite/client.d.ts +8 -1
  412. package/dist/vite/client.js +63 -12
  413. package/dist/vite/index.d.ts +1 -0
  414. package/dist/vite/index.js +1 -0
  415. package/docs/AGENTS.md +7 -2
  416. package/docs/SKILL.md +7 -5
  417. package/docs/content/agent-native-config.mdx +165 -0
  418. package/docs/content/agent-native-toolkit.mdx +1 -1
  419. package/docs/content/deployment.mdx +7 -2
  420. package/docs/content/doctor.mdx +21 -13
  421. package/docs/content/environment-variables.mdx +158 -0
  422. package/docs/content/file-uploads.mdx +1 -1
  423. package/docs/content/getting-started.mdx +1 -1
  424. package/docs/content/key-concepts.mdx +1 -1
  425. package/docs/content/multi-app-workspace.mdx +1 -1
  426. package/docs/content/template-clips-ai-and-editing.mdx +6 -6
  427. package/docs/content/template-clips-developers.mdx +3 -3
  428. package/docs/content/toolkit-settings.mdx +1 -1
  429. package/docs/content/voice-input.mdx +4 -4
  430. package/package.json +7 -2
  431. package/src/eject/provider-api-definitions.ts +1 -0
  432. package/src/eject/remote-mcp-presets.ts +1 -0
  433. package/src/templates/chat/.agents/skills/agent-native-docs/SKILL.md +23 -3
  434. package/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  435. package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +23 -2
  436. package/src/templates/chat/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  437. package/src/templates/chat/AGENTS.md +3 -0
  438. package/src/templates/chat/DESIGN.md +28 -0
  439. package/src/templates/chat/agent-native.json +12 -0
  440. package/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +23 -3
  441. package/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  442. package/src/templates/default/.agents/skills/frontend-design/SKILL.md +23 -2
  443. package/src/templates/default/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  444. package/src/templates/default/AGENTS.md +4 -0
  445. package/src/templates/default/DESIGN.md +30 -0
  446. package/src/templates/default/agent-native.json +9 -0
  447. package/src/templates/default/app/i18n/ar-SA.ts +2 -2
  448. package/src/templates/default/app/i18n/de-DE.ts +2 -2
  449. package/src/templates/default/app/i18n/en-US.ts +2 -2
  450. package/src/templates/default/app/i18n/es-ES.ts +2 -2
  451. package/src/templates/default/app/i18n/fr-FR.ts +2 -2
  452. package/src/templates/default/app/i18n/hi-IN.ts +2 -2
  453. package/src/templates/default/app/i18n/ja-JP.ts +2 -2
  454. package/src/templates/default/app/i18n/ko-KR.ts +2 -2
  455. package/src/templates/default/app/i18n/pt-BR.ts +2 -2
  456. package/src/templates/default/app/i18n/zh-CN.ts +2 -2
  457. package/src/templates/default/app/i18n/zh-TW.ts +1 -1
  458. package/src/templates/default/package.json +1 -0
  459. package/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +23 -3
  460. package/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  461. package/src/templates/headless/agent-native.json +9 -0
  462. package/src/templates/headless/package.json +2 -0
  463. package/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +23 -3
  464. package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  465. package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +23 -2
  466. package/src/templates/workspace-core/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  467. package/src/templates/workspace-core/AGENTS.md +3 -0
  468. package/src/templates/workspace-core/DESIGN.md +35 -0
  469. package/src/templates/workspace-root/AGENTS.md +3 -0
  470. package/src/templates/workspace-root/DESIGN.md +35 -0
  471. package/src/templates/workspace-root/agent-native.json +9 -0
  472. package/src/templates/workspace-root/package.json +3 -0
@@ -0,0 +1,12 @@
1
+ {
2
+ "version": 1,
3
+ "onboarding": {
4
+ "firstRun": {
5
+ "development": "off",
6
+ "production": "connect-and-integrations"
7
+ }
8
+ },
9
+ "doctor": {
10
+ "failOnBuild": false
11
+ }
12
+ }
@@ -28,6 +28,7 @@ import {
28
28
  } from "@/components/ui/dropdown-menu";
29
29
  import { Spinner } from "@/components/ui/spinner";
30
30
  import { useMseVideoSource } from "@/hooks/use-mse-video-source";
31
+ import { usePlaybackPosition } from "@/hooks/use-playback-position";
31
32
  import {
32
33
  parsePlaybackSpeed,
33
34
  readPlaybackSpeedPreference,
@@ -265,9 +266,12 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
265
266
  [videoUrl],
266
267
  );
267
268
  const videoRef = useRef<HTMLVideoElement | null>(null);
269
+ const [playbackVideoEl, setPlaybackVideoEl] =
270
+ useState<HTMLVideoElement | null>(null);
268
271
  const setVideoNode = useCallback(
269
272
  (el: HTMLVideoElement | null) => {
270
273
  videoRef.current = el;
274
+ setPlaybackVideoEl(el);
271
275
  onVideoElementChange?.(el);
272
276
  },
273
277
  [onVideoElementChange],
@@ -408,6 +412,50 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
408
412
  () => embedProvider === "loom" || isLoomEmbedUrl(activeVideoSrc),
409
413
  [activeVideoSrc, embedProvider],
410
414
  );
415
+ const restorePlaybackPosition = useCallback(
416
+ (positionMs: number) => {
417
+ const v = videoRef.current;
418
+ if (!v || (startMs && startMs > 0)) return;
419
+ if (hasPlaybackStarted && !autoPlay) return;
420
+ if (!autoPlay && isPlayPending) return;
421
+ if (!autoPlay && v.currentTime > 0.5) return;
422
+
423
+ const visibleMs = clampSeek(
424
+ skipExcludedRange(positionMs, excludedRanges, resolvedDurationMs),
425
+ v,
426
+ resolvedDurationMs,
427
+ );
428
+ if (visibleMs <= 0) return;
429
+
430
+ try {
431
+ initialVisibleFrameSeekedRef.current = true;
432
+ v.currentTime = visibleMs / 1000;
433
+ setCurrentMs(visibleMs);
434
+ setCanPlay(true);
435
+ setIsPreparing(false);
436
+ onTimeUpdate?.(visibleMs, resolvedDurationMs);
437
+ } catch (error) {
438
+ console.warn("[clips] playback position restore failed", error);
439
+ }
440
+ },
441
+ [
442
+ autoPlay,
443
+ excludedRanges,
444
+ hasPlaybackStarted,
445
+ isPlayPending,
446
+ onTimeUpdate,
447
+ resolvedDurationMs,
448
+ startMs,
449
+ ],
450
+ );
451
+ usePlaybackPosition({
452
+ recordingId,
453
+ videoEl: playbackVideoEl,
454
+ durationMs,
455
+ explicitStartMs: startMs,
456
+ allowRestoreWhilePlaying: autoPlay,
457
+ onRestore: restorePlaybackPosition,
458
+ });
411
459
  // Clips stores exactly one `videoUrl` per recording (no alternate-format
412
460
  // fallback to select between), and every browser MediaRecorder-based
413
461
  // recording is stored as `webm` — which Safari (desktop and iOS) cannot
@@ -1291,11 +1339,12 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
1291
1339
  ? "loading"
1292
1340
  : "ready"
1293
1341
  : null;
1294
- const centerOverlayLabel = isPlayPending
1295
- ? "Starting playback"
1296
- : isBuffering
1297
- ? "Buffering"
1298
- : "Preparing clip";
1342
+ const centerOverlayLabel =
1343
+ isPlayPending && !hasPlaybackStarted
1344
+ ? "Starting playback"
1345
+ : isPlayPending || isBuffering
1346
+ ? "Buffering"
1347
+ : "Preparing clip";
1299
1348
 
1300
1349
  return (
1301
1350
  <div
@@ -0,0 +1,188 @@
1
+ import { useEffect, useRef } from "react";
2
+
3
+ import {
4
+ getPlaybackPosition,
5
+ savePlaybackPosition,
6
+ } from "@/lib/playback-position";
7
+
8
+ const SAVE_INTERVAL_MS = 5_000;
9
+ const MIN_POSITION_MS = 50;
10
+ const COMPLETION_TAIL_MS = 1_500;
11
+
12
+ export interface UsePlaybackPositionOptions {
13
+ recordingId: string;
14
+ videoEl: HTMLVideoElement | null;
15
+ durationMs: number;
16
+ explicitStartMs?: number;
17
+ allowRestoreWhilePlaying?: boolean;
18
+ onRestore?: (positionMs: number) => void;
19
+ }
20
+
21
+ /**
22
+ * Persists the latest native-video position for the current viewer. This is
23
+ * separate from view analytics so the recording owner can resume without
24
+ * becoming one of the clip's counted viewers.
25
+ */
26
+ export function usePlaybackPosition({
27
+ recordingId,
28
+ videoEl,
29
+ durationMs,
30
+ explicitStartMs,
31
+ allowRestoreWhilePlaying = false,
32
+ onRestore,
33
+ }: UsePlaybackPositionOptions) {
34
+ const durationMsRef = useRef(durationMs);
35
+ const onRestoreRef = useRef(onRestore);
36
+
37
+ durationMsRef.current = durationMs;
38
+ onRestoreRef.current = onRestore;
39
+
40
+ useEffect(() => {
41
+ if (!videoEl || !recordingId) return;
42
+
43
+ const controller = new AbortController();
44
+ let cancelled = false;
45
+ let playbackStarted = false;
46
+ let restoreApplied = false;
47
+ let saveInFlight = false;
48
+ let pendingSave: { positionMs: number; keepalive: boolean } | null = null;
49
+ let lastSavedPositionMs = -1;
50
+ let lastSavedAt = -SAVE_INTERVAL_MS;
51
+ let removePendingRestoreListeners: (() => void) | null = null;
52
+
53
+ const readPositionMs = (): number | null => {
54
+ const seconds = videoEl.currentTime;
55
+ if (!Number.isFinite(seconds) || seconds < 0 || seconds >= 1e7) {
56
+ return null;
57
+ }
58
+ return Math.floor(seconds * 1000);
59
+ };
60
+
61
+ const persist = (keepalive: boolean) => {
62
+ const positionMs = readPositionMs();
63
+ if (
64
+ positionMs === null ||
65
+ (!playbackStarted && positionMs < MIN_POSITION_MS)
66
+ ) {
67
+ return;
68
+ }
69
+
70
+ const now = Date.now();
71
+ if (!keepalive && now - lastSavedAt < SAVE_INTERVAL_MS) {
72
+ return;
73
+ }
74
+
75
+ if (saveInFlight) {
76
+ pendingSave = { positionMs, keepalive };
77
+ return;
78
+ }
79
+
80
+ saveInFlight = true;
81
+ lastSavedPositionMs = positionMs;
82
+ lastSavedAt = now;
83
+ void savePlaybackPosition(recordingId, positionMs, { keepalive })
84
+ .catch((error) => {
85
+ if (!cancelled) {
86
+ console.warn("[clips] playback position save failed", error);
87
+ }
88
+ })
89
+ .finally(() => {
90
+ saveInFlight = false;
91
+ if (!pendingSave) return;
92
+ const next = pendingSave;
93
+ pendingSave = null;
94
+ persist(next.keepalive);
95
+ });
96
+ };
97
+
98
+ const restore = (positionMs: number) => {
99
+ if (cancelled || restoreApplied || explicitStartMs) return;
100
+ if (positionMs <= 0) return;
101
+ const duration = durationMsRef.current;
102
+ if (duration > 0 && positionMs >= duration - COMPLETION_TAIL_MS) {
103
+ return;
104
+ }
105
+ if (
106
+ playbackStarted &&
107
+ !allowRestoreWhilePlaying &&
108
+ readPositionMs() !== 0
109
+ ) {
110
+ return;
111
+ }
112
+
113
+ restoreApplied = true;
114
+ onRestoreRef.current?.(positionMs);
115
+ };
116
+
117
+ const restoreWhenReady = (positionMs: number) => {
118
+ if (videoEl.readyState >= 1) {
119
+ restore(positionMs);
120
+ return;
121
+ }
122
+
123
+ const apply = () => {
124
+ removePendingRestoreListeners?.();
125
+ removePendingRestoreListeners = null;
126
+ restore(positionMs);
127
+ };
128
+ videoEl.addEventListener("loadedmetadata", apply);
129
+ videoEl.addEventListener("loadeddata", apply);
130
+ removePendingRestoreListeners = () => {
131
+ videoEl.removeEventListener("loadedmetadata", apply);
132
+ videoEl.removeEventListener("loadeddata", apply);
133
+ };
134
+ };
135
+
136
+ const onPlay = () => {
137
+ playbackStarted = true;
138
+ };
139
+ const onTimeUpdate = () => {
140
+ if (playbackStarted) persist(false);
141
+ };
142
+ const onPause = () => persist(true);
143
+ const onSeeked = () => persist(true);
144
+ const onEnded = () => persist(true);
145
+ const onPageHide = () => persist(true);
146
+ const onVisibilityChange = () => {
147
+ if (document.visibilityState === "hidden") persist(true);
148
+ };
149
+
150
+ videoEl.addEventListener("play", onPlay);
151
+ videoEl.addEventListener("timeupdate", onTimeUpdate);
152
+ videoEl.addEventListener("pause", onPause);
153
+ videoEl.addEventListener("seeked", onSeeked);
154
+ videoEl.addEventListener("ended", onEnded);
155
+ window.addEventListener("pagehide", onPageHide);
156
+ document.addEventListener("visibilitychange", onVisibilityChange);
157
+
158
+ if (!explicitStartMs) {
159
+ void getPlaybackPosition(recordingId, { signal: controller.signal })
160
+ .then((positionMs) => {
161
+ if (positionMs !== null) restoreWhenReady(positionMs);
162
+ })
163
+ .catch((error) => {
164
+ if (
165
+ !cancelled &&
166
+ (error as { name?: string })?.name !== "AbortError"
167
+ ) {
168
+ console.warn("[clips] playback position load failed", error);
169
+ }
170
+ });
171
+ }
172
+
173
+ return () => {
174
+ persist(true);
175
+ cancelled = true;
176
+ controller.abort();
177
+ removePendingRestoreListeners?.();
178
+ removePendingRestoreListeners = null;
179
+ videoEl.removeEventListener("play", onPlay);
180
+ videoEl.removeEventListener("timeupdate", onTimeUpdate);
181
+ videoEl.removeEventListener("pause", onPause);
182
+ videoEl.removeEventListener("seeked", onSeeked);
183
+ videoEl.removeEventListener("ended", onEnded);
184
+ window.removeEventListener("pagehide", onPageHide);
185
+ document.removeEventListener("visibilitychange", onVisibilityChange);
186
+ };
187
+ }, [allowRestoreWhilePlaying, explicitStartMs, recordingId, videoEl]);
188
+ }
@@ -1,27 +1,9 @@
1
1
  import { appBasePath } from "@agent-native/core/client/api-path";
2
2
  import { useEffect, useRef } from "react";
3
3
 
4
- import { clampCompletionPct } from "../../shared/view-analytics";
5
-
6
- const SESSION_KEY = "clips-view-session-id";
4
+ import { getViewerSessionId } from "@/lib/viewer-session";
7
5
 
8
- function getSessionId(): string {
9
- if (typeof window === "undefined") return "server";
10
- try {
11
- let id = localStorage.getItem(SESSION_KEY);
12
- if (!id) {
13
- id =
14
- "s-" +
15
- Date.now().toString(36) +
16
- "-" +
17
- Math.random().toString(36).slice(2, 8);
18
- localStorage.setItem(SESSION_KEY, id);
19
- }
20
- return id;
21
- } catch {
22
- return "s-" + Math.random().toString(36).slice(2, 8);
23
- }
24
- }
6
+ import { clampCompletionPct } from "../../shared/view-analytics";
25
7
 
26
8
  function createViewSessionId(recordingId: string): string {
27
9
  return [
@@ -118,7 +100,7 @@ export function useViewTracking(opts: UseViewTrackingOpts) {
118
100
  recordingId,
119
101
  kind: "view-start",
120
102
  timestampMs: 0,
121
- sessionId: getSessionId(),
103
+ sessionId: getViewerSessionId(),
122
104
  viewSessionId: viewSessionRef.current,
123
105
  totalWatchMs: 0,
124
106
  completedPct: 0,
@@ -130,7 +112,7 @@ export function useViewTracking(opts: UseViewTrackingOpts) {
130
112
  }
131
113
 
132
114
  const video = videoEl;
133
- const sessionId = getSessionId();
115
+ const sessionId = getViewerSessionId();
134
116
  viewSessionRef.current = createViewSessionId(recordingId);
135
117
  let progressTimer: ReturnType<typeof setInterval> | null = null;
136
118
 
@@ -243,7 +225,7 @@ export function useViewTracking(opts: UseViewTrackingOpts) {
243
225
  body: JSON.stringify({
244
226
  recordingId: recordingIdRef.current,
245
227
  kind: "cta-click",
246
- sessionId: getSessionId(),
228
+ sessionId: getViewerSessionId(),
247
229
  }),
248
230
  }).catch(() => {});
249
231
  },
@@ -255,7 +237,7 @@ export function useViewTracking(opts: UseViewTrackingOpts) {
255
237
  body: JSON.stringify({
256
238
  recordingId: recordingIdRef.current,
257
239
  kind: "reaction",
258
- sessionId: getSessionId(),
240
+ sessionId: getViewerSessionId(),
259
241
  payload: { emoji },
260
242
  }),
261
243
  }).catch(() => {});
@@ -0,0 +1,99 @@
1
+ import {
2
+ callAction,
3
+ tryCallActionKeepalive,
4
+ } from "@agent-native/core/client/hooks";
5
+
6
+ import { getViewerSessionId } from "./viewer-session";
7
+
8
+ export interface PlaybackPositionRecord {
9
+ recordingId: string;
10
+ viewerKey: string;
11
+ viewerEmail: string | null;
12
+ positionMs: number;
13
+ updatedAt: string | null;
14
+ }
15
+
16
+ interface PlaybackPositionActionResult {
17
+ playbackPosition: PlaybackPositionRecord | null;
18
+ }
19
+
20
+ function parsePlaybackPosition(payload: unknown): number | null {
21
+ if (
22
+ !payload ||
23
+ typeof payload !== "object" ||
24
+ !("playbackPosition" in payload)
25
+ ) {
26
+ throw new Error("Invalid playback position response");
27
+ }
28
+ const playbackPosition = (payload as { playbackPosition?: unknown })
29
+ .playbackPosition;
30
+ if (playbackPosition === null) return null;
31
+ if (typeof playbackPosition !== "object") {
32
+ throw new Error("Invalid playback position payload");
33
+ }
34
+ const positionMs = (playbackPosition as { positionMs?: unknown }).positionMs;
35
+ if (
36
+ typeof positionMs !== "number" ||
37
+ !Number.isFinite(positionMs) ||
38
+ positionMs < 0
39
+ ) {
40
+ throw new Error("Invalid playback position payload");
41
+ }
42
+ return positionMs;
43
+ }
44
+
45
+ export async function getPlaybackPosition(
46
+ recordingId: string,
47
+ options: {
48
+ sessionId?: string;
49
+ signal?: AbortSignal;
50
+ } = {},
51
+ ): Promise<number | null> {
52
+ const sessionId = options.sessionId ?? getViewerSessionId();
53
+ const payload = await callAction<PlaybackPositionActionResult>(
54
+ "get-playback-position",
55
+ { recordingId, sessionId },
56
+ { method: "GET", signal: options.signal },
57
+ );
58
+ return parsePlaybackPosition(payload);
59
+ }
60
+
61
+ export async function savePlaybackPosition(
62
+ recordingId: string,
63
+ positionMs: number,
64
+ options: {
65
+ sessionId?: string;
66
+ signal?: AbortSignal;
67
+ keepalive?: boolean;
68
+ } = {},
69
+ ): Promise<void> {
70
+ const sessionId = options.sessionId ?? getViewerSessionId();
71
+ const params = { recordingId, positionMs, sessionId };
72
+
73
+ if (options.keepalive) {
74
+ const request = tryCallActionKeepalive<PlaybackPositionActionResult>(
75
+ "save-playback-position",
76
+ params,
77
+ { signal: options.signal },
78
+ );
79
+ if (!request.accepted) {
80
+ throw new Error(
81
+ `Failed to save playback position during unload (${request.reason})`,
82
+ );
83
+ }
84
+ const payload = await request.completion;
85
+ if (parsePlaybackPosition(payload) === null) {
86
+ throw new Error("Invalid playback position payload");
87
+ }
88
+ return;
89
+ }
90
+
91
+ const payload = await callAction<PlaybackPositionActionResult>(
92
+ "save-playback-position",
93
+ params,
94
+ { signal: options.signal },
95
+ );
96
+ if (parsePlaybackPosition(payload) === null) {
97
+ throw new Error("Invalid playback position payload");
98
+ }
99
+ }
@@ -0,0 +1,29 @@
1
+ const VIEWER_SESSION_STORAGE_KEY = "clips-view-session-id";
2
+ let inMemoryViewerSessionId: string | null = null;
3
+
4
+ function fallbackSessionId(): string {
5
+ return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
6
+ }
7
+
8
+ export function getViewerSessionId(): string {
9
+ if (typeof window === "undefined") {
10
+ if (inMemoryViewerSessionId) return inMemoryViewerSessionId;
11
+ inMemoryViewerSessionId = fallbackSessionId();
12
+ return inMemoryViewerSessionId;
13
+ }
14
+
15
+ try {
16
+ const existing = window.localStorage.getItem(VIEWER_SESSION_STORAGE_KEY);
17
+ if (existing) return existing;
18
+ const next =
19
+ typeof window.crypto?.randomUUID === "function"
20
+ ? window.crypto.randomUUID()
21
+ : fallbackSessionId();
22
+ window.localStorage.setItem(VIEWER_SESSION_STORAGE_KEY, next);
23
+ return next;
24
+ } catch {
25
+ if (inMemoryViewerSessionId) return inMemoryViewerSessionId;
26
+ inMemoryViewerSessionId = fallbackSessionId();
27
+ return inMemoryViewerSessionId;
28
+ }
29
+ }
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-08-05
4
+ ---
5
+
6
+ Clip buffering now shows buffering copy after playback starts.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-08-05
4
+ ---
5
+
6
+ Clips remembers your playback position when you reopen a clip.
@@ -24,7 +24,7 @@
24
24
  ## Meetings & Dictate
25
25
 
26
26
  - When a user says **"meeting"** they mean a Meetings tab entry, not a Clips recording — _unless_ the recording is linked to a meeting (i.e. `recordings.meeting_id` is non-null), in which case both interpretations are valid and worth mentioning.
27
- - When suggesting how to enable transcript improvements (cleanup, summary, action items), **lead with Builder.io Connect** — it's the easiest path and requires no key. Mention a BYOK `GEMINI_API_KEY` only as a secondary fallback. The cleanup pipeline does not use direct Groq or OpenAI keys by default; it prefers Luna through Builder or OpenAI, with Gemini as the fallback.
27
+ - When suggesting how to enable transcript improvements (cleanup, summary, action items), **lead with Builder.io Connect** — its free tier is available, it's the easiest path, and it requires no key. Mention a BYOK `GEMINI_API_KEY` only as a secondary fallback. The cleanup pipeline does not use direct Groq or OpenAI keys by default; it prefers Luna through Builder or OpenAI, with Gemini as the fallback.
28
28
  - **Per-attendee action items require attendees to actually speak in the recorded audio.** With mic + system audio capture (Meetings default) both sides are heard and tagged by source. With mic-only capture (and all Dictate dictations), remote attendees may be silent in the transcript — call this out before promising attendee-level coverage.
29
29
 
30
30
  ## Platform requirements
@@ -404,6 +404,24 @@ export const recordingViews = table("recording_views", {
404
404
  viewedAt: text("viewed_at").notNull().default(now()),
405
405
  });
406
406
 
407
+ export const recordingPlaybackPositions = table(
408
+ "recording_playback_positions",
409
+ {
410
+ id: text("id").primaryKey(),
411
+ recordingId: text("recording_id").notNull(),
412
+ viewerKey: text("viewer_key").notNull(),
413
+ viewerEmail: text("viewer_email"),
414
+ positionMs: integer("position_ms").notNull().default(0),
415
+ updatedAt: text("updated_at").notNull().default(now()),
416
+ createdAt: text("created_at").notNull().default(now()),
417
+ },
418
+ (position) => ({
419
+ recordingPlaybackPositionUnique: uniqueIndex(
420
+ "recording_playback_positions_recording_viewer_key_unique_idx",
421
+ ).on(position.recordingId, position.viewerKey),
422
+ }),
423
+ );
424
+
407
425
  // Agent views — one row per (clip, agent, time bucket). Deliberately separate
408
426
  // from `recording_viewers` / `recording_views` so no human-view count can ever
409
427
  // pick agents up by forgetting a filter: the human tables stay agent-free.