@agent-native/core 0.137.8 → 0.138.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 (422) 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/first-party-analytics-health.ts +397 -0
  22. package/corpus/templates/analytics/server/lib/first-party-analytics-rollups.ts +182 -0
  23. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +86 -15
  24. package/corpus/templates/analytics/server/lib/provider-api.ts +20 -1
  25. package/corpus/templates/analytics/server/lib/replay-storage.ts +1 -1
  26. package/corpus/templates/analytics/server/plugins/agent-chat.ts +1 -0
  27. package/corpus/templates/analytics/server/plugins/db.ts +60 -0
  28. package/corpus/templates/assets/.agents/skills/agent-native-docs/SKILL.md +23 -3
  29. package/corpus/templates/assets/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  30. package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +23 -2
  31. package/corpus/templates/assets/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  32. package/corpus/templates/assets/agent-native.json +12 -0
  33. package/corpus/templates/assets/server/lib/generation.ts +8 -8
  34. package/corpus/templates/assets/server/lib/storage.ts +1 -1
  35. package/corpus/templates/assets/server/plugins/onboarding.ts +1 -1
  36. package/corpus/templates/brain/.agents/skills/agent-native-docs/SKILL.md +23 -3
  37. package/corpus/templates/brain/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  38. package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +23 -2
  39. package/corpus/templates/brain/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  40. package/corpus/templates/brain/agent-native.json +12 -0
  41. package/corpus/templates/calendar/.agents/skills/agent-native-docs/SKILL.md +23 -3
  42. package/corpus/templates/calendar/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  43. package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +23 -2
  44. package/corpus/templates/calendar/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  45. package/corpus/templates/calendar/agent-native.json +12 -0
  46. package/corpus/templates/chat/.agents/skills/agent-native-docs/SKILL.md +23 -3
  47. package/corpus/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  48. package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +23 -2
  49. package/corpus/templates/chat/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  50. package/corpus/templates/chat/AGENTS.md +3 -0
  51. package/corpus/templates/chat/DESIGN.md +28 -0
  52. package/corpus/templates/chat/agent-native.json +12 -0
  53. package/corpus/templates/clips/.agents/skills/agent-native-docs/SKILL.md +23 -3
  54. package/corpus/templates/clips/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  55. package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +23 -2
  56. package/corpus/templates/clips/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  57. package/corpus/templates/clips/actions/cleanup-transcript.ts +2 -2
  58. package/corpus/templates/clips/actions/delete-recording-permanent.ts +3 -0
  59. package/corpus/templates/clips/actions/get-playback-position.ts +68 -0
  60. package/corpus/templates/clips/actions/import-loom-recording.ts +2 -2
  61. package/corpus/templates/clips/actions/save-playback-position.ts +80 -0
  62. package/corpus/templates/clips/actions/set-thumbnail.ts +1 -1
  63. package/corpus/templates/clips/agent-native.json +12 -0
  64. package/corpus/templates/clips/app/components/player/video-player.tsx +54 -5
  65. package/corpus/templates/clips/app/hooks/use-playback-position.ts +188 -0
  66. package/corpus/templates/clips/app/hooks/use-view-tracking.ts +6 -24
  67. package/corpus/templates/clips/app/lib/playback-position.ts +99 -0
  68. package/corpus/templates/clips/app/lib/viewer-session.ts +29 -0
  69. package/corpus/templates/clips/changelog/2026-08-05-clip-buffering-now-uses-buffering-copy-after-playback.md +6 -0
  70. package/corpus/templates/clips/changelog/2026-08-05-clips-remembers-your-playback-position-when-you-reopen-a-cli.md +6 -0
  71. package/corpus/templates/clips/learnings.defaults.md +1 -1
  72. package/corpus/templates/clips/server/db/schema.ts +18 -0
  73. package/corpus/templates/clips/server/lib/public-agent-context.ts +1 -1
  74. package/corpus/templates/clips/server/lib/video-storage.ts +1 -1
  75. package/corpus/templates/clips/server/plugins/db.ts +15 -0
  76. package/corpus/templates/clips/server/routes/api/media/index.post.ts +1 -1
  77. package/corpus/templates/content/.agents/skills/agent-native-docs/SKILL.md +23 -3
  78. package/corpus/templates/content/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  79. package/corpus/templates/content/.agents/skills/document-editing/references/databases.md +13 -0
  80. package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +23 -2
  81. package/corpus/templates/content/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  82. package/corpus/templates/content/AGENTS.md +1 -0
  83. package/corpus/templates/content/actions/_content-database-mutation-lock.ts +41 -0
  84. package/corpus/templates/content/actions/_content-database-row-migration.ts +569 -0
  85. package/corpus/templates/content/actions/_database-source-utils.ts +82 -36
  86. package/corpus/templates/content/actions/_database-utils.ts +5 -0
  87. package/corpus/templates/content/actions/_delete-content-space.ts +25 -11
  88. package/corpus/templates/content/actions/add-database-item.ts +60 -42
  89. package/corpus/templates/content/actions/attach-content-database-source.ts +2 -0
  90. package/corpus/templates/content/actions/configure-document-property.ts +99 -104
  91. package/corpus/templates/content/actions/delete-content-database.ts +19 -7
  92. package/corpus/templates/content/actions/delete-document-property.ts +47 -58
  93. package/corpus/templates/content/actions/delete-document.ts +390 -167
  94. package/corpus/templates/content/actions/disconnect-content-database-source.ts +41 -24
  95. package/corpus/templates/content/actions/duplicate-database-item.ts +63 -31
  96. package/corpus/templates/content/actions/duplicate-database-items.ts +86 -43
  97. package/corpus/templates/content/actions/duplicate-document-property.ts +37 -14
  98. package/corpus/templates/content/actions/migrate-content-database-rows.ts +830 -0
  99. package/corpus/templates/content/actions/move-database-item.ts +14 -0
  100. package/corpus/templates/content/actions/permanently-delete-document.ts +27 -6
  101. package/corpus/templates/content/actions/remove-database-items.ts +13 -0
  102. package/corpus/templates/content/actions/reorder-document-property.ts +45 -46
  103. package/corpus/templates/content/actions/set-document-property.ts +68 -28
  104. package/corpus/templates/content/actions/submit-content-database-form.ts +49 -0
  105. package/corpus/templates/content/actions/transcribe-media.ts +1 -1
  106. package/corpus/templates/content/agent-native.json +12 -0
  107. package/corpus/templates/content/app/components/editor/image-upload.ts +2 -2
  108. package/corpus/templates/content/app/i18n-data.ts +1 -1
  109. package/corpus/templates/content/changelog/2026-08-01-content-can-reorganize-every-row-in-an-existing-database-as-.md +6 -0
  110. package/corpus/templates/content/parity/matrix.md +1 -1
  111. package/corpus/templates/content/parity/matrix.ts +4 -2
  112. package/corpus/templates/content/server/db/schema.ts +30 -0
  113. package/corpus/templates/content/server/plugins/db.ts +24 -0
  114. package/corpus/templates/content/server/plugins/onboarding.ts +2 -2
  115. package/corpus/templates/crm/.agents/skills/agent-native-docs/SKILL.md +23 -3
  116. package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  117. package/corpus/templates/crm/agent-native.json +12 -0
  118. package/corpus/templates/design/.agents/skills/agent-native-docs/SKILL.md +23 -3
  119. package/corpus/templates/design/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  120. package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +23 -2
  121. package/corpus/templates/design/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  122. package/corpus/templates/design/CODE_NATIVE_DESIGN_STUDIO_IMPLEMENTATION_PLAN.md +2 -2
  123. package/corpus/templates/design/DESIGN-STUDIO-PLAN.md +2 -2
  124. package/corpus/templates/design/actions/apply-design-token-edit.ts +1 -1
  125. package/corpus/templates/design/actions/capture-design-state.ts +1 -1
  126. package/corpus/templates/design/actions/connect-builder-app.ts +2 -2
  127. package/corpus/templates/design/actions/create-design-branch.ts +1 -1
  128. package/corpus/templates/design/actions/create-fusion-app.ts +3 -3
  129. package/corpus/templates/design/actions/deploy-design-preview.ts +1 -1
  130. package/corpus/templates/design/actions/get-component-details.ts +1 -1
  131. package/corpus/templates/design/actions/get-design-branch-diff.ts +1 -1
  132. package/corpus/templates/design/actions/index-components.ts +3 -3
  133. package/corpus/templates/design/actions/index-design-system-with-builder.ts +1 -1
  134. package/corpus/templates/design/actions/migrate-inline-design-to-app.ts +3 -3
  135. package/corpus/templates/design/actions/open-component-source.ts +1 -1
  136. package/corpus/templates/design/actions/update-design.ts +61 -0
  137. package/corpus/templates/design/agent-native.json +12 -0
  138. package/corpus/templates/design/app/components/design/edit-panel/component-section.tsx +1 -1
  139. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +1 -1
  140. package/corpus/templates/design/scripts/qa-figma-stress-import.ts +1 -1
  141. package/corpus/templates/design/server/lib/figma-node-import.ts +1 -1
  142. package/corpus/templates/design/shared/design-source-capabilities.ts +25 -9
  143. package/corpus/templates/dispatch/.agents/skills/agent-native-docs/SKILL.md +23 -3
  144. package/corpus/templates/dispatch/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  145. package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +23 -2
  146. package/corpus/templates/dispatch/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  147. package/corpus/templates/dispatch/agent-native.json +12 -0
  148. package/corpus/templates/factory/.agents/skills/agent-native-docs/SKILL.md +23 -3
  149. package/corpus/templates/factory/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  150. package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +23 -2
  151. package/corpus/templates/factory/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  152. package/corpus/templates/factory/agent-native.json +12 -0
  153. package/corpus/templates/forms/.agents/skills/agent-native-docs/SKILL.md +23 -3
  154. package/corpus/templates/forms/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  155. package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +23 -2
  156. package/corpus/templates/forms/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  157. package/corpus/templates/forms/actions/export-responses.ts +1 -1
  158. package/corpus/templates/forms/agent-native.json +12 -0
  159. package/corpus/templates/macros/.agents/skills/agent-native-docs/SKILL.md +23 -3
  160. package/corpus/templates/macros/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  161. package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +23 -2
  162. package/corpus/templates/macros/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  163. package/corpus/templates/macros/agent-native.json +12 -0
  164. package/corpus/templates/mail/.agents/skills/agent-native-docs/SKILL.md +23 -3
  165. package/corpus/templates/mail/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  166. package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +23 -2
  167. package/corpus/templates/mail/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  168. package/corpus/templates/mail/agent-native.json +12 -0
  169. package/corpus/templates/mail/app/i18n/en-US.ts +1 -1
  170. package/corpus/templates/mail/server/lib/media-upload.ts +1 -1
  171. package/corpus/templates/plan/.agents/skills/agent-native-docs/SKILL.md +23 -3
  172. package/corpus/templates/plan/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  173. package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +23 -2
  174. package/corpus/templates/plan/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  175. package/corpus/templates/plan/agent-native.json +12 -0
  176. package/corpus/templates/plan/server/lib/plan-assets.ts +1 -1
  177. package/corpus/templates/slides/.agents/skills/agent-native-docs/SKILL.md +23 -3
  178. package/corpus/templates/slides/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  179. package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +23 -2
  180. package/corpus/templates/slides/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  181. package/corpus/templates/slides/actions/generate-image-api.ts +1 -1
  182. package/corpus/templates/slides/actions/generate-slides-ai.ts +1 -1
  183. package/corpus/templates/slides/actions/import-file.ts +2 -2
  184. package/corpus/templates/slides/actions/index-design-system-with-builder.ts +1 -1
  185. package/corpus/templates/slides/agent-native.json +12 -0
  186. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +1 -1
  187. package/corpus/templates/slides/app/i18n/en-US.ts +2 -2
  188. package/corpus/templates/slides/app/lib/deck-sorting.ts +19 -0
  189. package/corpus/templates/slides/app/lib/image-drop-to-agent.ts +1 -1
  190. package/corpus/templates/slides/app/pages/Index.tsx +7 -2
  191. package/corpus/templates/slides/changelog/2026-08-05-decks-are-now-sorted-by-most-recently-updated.md +6 -0
  192. package/corpus/templates/slides/server/handlers/assets.ts +1 -1
  193. package/corpus/templates/slides/server/handlers/uploads.ts +1 -1
  194. package/corpus/templates/tasks/.agents/skills/agent-native-docs/SKILL.md +23 -3
  195. package/corpus/templates/tasks/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  196. package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +23 -2
  197. package/corpus/templates/tasks/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  198. package/corpus/templates/tasks/agent-native.json +12 -0
  199. package/dist/action.d.ts +6 -0
  200. package/dist/agent/engine/builder-engine.js +2 -2
  201. package/dist/agent/engine/credential-errors.d.ts +1 -1
  202. package/dist/agent/engine/credential-errors.js +2 -2
  203. package/dist/agent/production-agent.js +3 -2
  204. package/dist/brand-kit/fig/index.js +1 -1
  205. package/dist/cli/agent.js +45 -3
  206. package/dist/cli/code-agent-executor.js +2 -1
  207. package/dist/cli/create.d.ts +9 -1
  208. package/dist/cli/create.js +94 -1
  209. package/dist/cli/doctor.d.ts +8 -11
  210. package/dist/cli/doctor.js +92 -24
  211. package/dist/cli/index.js +6 -5
  212. package/dist/client/AgentAskPopover.d.ts +3 -1
  213. package/dist/client/AgentAskPopover.js +2 -2
  214. package/dist/client/AgentPanel.js +9 -3
  215. package/dist/client/AssistantChat.js +54 -33
  216. package/dist/client/MultiTabAssistantChat.js +1 -1
  217. package/dist/client/RouteTransitionIndicator.d.ts +7 -0
  218. package/dist/client/RouteTransitionIndicator.js +31 -0
  219. package/dist/client/agent-engine-key.js +1 -1
  220. package/dist/client/app-providers.js +11 -2
  221. package/dist/client/chat/message-components.js +1 -1
  222. package/dist/client/chat/run-recovery.js +1 -1
  223. package/dist/client/chat/tool-call-display.d.ts +3 -1
  224. package/dist/client/chat/tool-call-display.js +4 -3
  225. package/dist/client/chat-model-groups.d.ts +6 -0
  226. package/dist/client/chat-model-groups.js +11 -0
  227. package/dist/client/error-format.js +1 -1
  228. package/dist/client/i18n.js +1 -1
  229. package/dist/client/onboarding/FirstRunOnboarding.d.ts +5 -1
  230. package/dist/client/onboarding/FirstRunOnboarding.js +29 -13
  231. package/dist/client/onboarding/first-run-enabled.d.ts +6 -1
  232. package/dist/client/onboarding/first-run-enabled.js +33 -3
  233. package/dist/client/onboarding/use-onboarding.js +16 -11
  234. package/dist/client/resources/mcp-integration-catalog.js +26 -0
  235. package/dist/client/resources/mcp-integration-logos.js +4 -0
  236. package/dist/client/route-warmup.js +56 -10
  237. package/dist/client/settings/AccountSettingsCard.js +78 -3
  238. package/dist/client/settings/SettingsPanel.js +1 -1
  239. package/dist/client/settings/VoiceTranscriptionSection.js +2 -2
  240. package/dist/client/settings/useBuilderStatus.js +1 -1
  241. package/dist/client/setup-connections/useBuilderConnectCardController.js +1 -1
  242. package/dist/client/ui/index.d.ts +1 -0
  243. package/dist/client/ui/index.js +1 -0
  244. package/dist/client/uploads/upload-editor-image.js +1 -1
  245. package/dist/client/use-chat-threads.js +3 -0
  246. package/dist/collab/routes.d.ts +2 -2
  247. package/dist/collab/struct-routes.d.ts +1 -1
  248. package/dist/config.d.ts +48 -0
  249. package/dist/config.js +111 -0
  250. package/dist/db/migrations.js +5 -0
  251. package/dist/eject/provider-api-definitions.d.ts +1 -1
  252. package/dist/eject/provider-api-definitions.js +1 -0
  253. package/dist/eject/remote-mcp-presets.js +1 -0
  254. package/dist/extensions/web-search-tool.js +2 -2
  255. package/dist/file-upload/actions/upload-image.js +1 -1
  256. package/dist/file-upload/registry.js +1 -1
  257. package/dist/guards/index.d.ts +3 -0
  258. package/dist/guards/index.js +2 -0
  259. package/dist/guards/no-empty-migrations.d.ts +14 -0
  260. package/dist/guards/no-empty-migrations.js +126 -0
  261. package/dist/index.browser.d.ts +1 -0
  262. package/dist/index.browser.js +3 -0
  263. package/dist/index.d.ts +1 -0
  264. package/dist/index.js +1 -0
  265. package/dist/localization/default-messages.d.ts +24 -0
  266. package/dist/localization/default-messages.js +26 -2
  267. package/dist/notifications/routes.d.ts +3 -3
  268. package/dist/onboarding/app-profile.js +1 -1
  269. package/dist/onboarding/plugin.d.ts +2 -0
  270. package/dist/onboarding/plugin.js +29 -2
  271. package/dist/provider-api/actions/custom-provider-registration.d.ts +16 -16
  272. package/dist/provider-api/actions/provider-api.d.ts +13 -13
  273. package/dist/provider-api/index.d.ts +4 -4
  274. package/dist/provider-api/index.js +35 -0
  275. package/dist/resources/handlers.d.ts +1 -1
  276. package/dist/resources/handlers.js +1 -1
  277. package/dist/scripts/docs/framework-search.d.ts +9 -0
  278. package/dist/scripts/docs/framework-search.js +239 -0
  279. package/dist/scripts/docs/index.js +1 -0
  280. package/dist/scripts/docs/search.d.ts +10 -0
  281. package/dist/scripts/docs/search.js +1 -1
  282. package/dist/scripts/docs/source-search.d.ts +10 -2
  283. package/dist/scripts/docs/source-search.js +108 -41
  284. package/dist/search-utils/index.d.ts +11 -0
  285. package/dist/search-utils/index.js +72 -0
  286. package/dist/server/action-change.d.ts +6 -0
  287. package/dist/server/action-change.js +28 -14
  288. package/dist/server/action-discovery.js +9 -0
  289. package/dist/server/action-routes.js +1 -0
  290. package/dist/server/agent-chat/browser-team-tools.js +1 -1
  291. package/dist/server/agent-chat/script-entries.js +43 -2
  292. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  293. package/dist/server/auth-login-mode.d.ts +8 -0
  294. package/dist/server/auth-login-mode.js +17 -0
  295. package/dist/server/auth.js +100 -15
  296. package/dist/server/better-auth-instance.d.ts +36 -0
  297. package/dist/server/better-auth-instance.js +25 -3
  298. package/dist/server/builder-design-systems.js +1 -1
  299. package/dist/server/core-routes-plugin.js +17 -14
  300. package/dist/server/credential-provider.js +3 -3
  301. package/dist/server/email-templates.d.ts +7 -0
  302. package/dist/server/email-templates.js +24 -0
  303. package/dist/server/email.d.ts +17 -0
  304. package/dist/server/email.js +22 -1
  305. package/dist/server/framework-request-handler.js +6 -0
  306. package/dist/server/onboarding-html.d.ts +2 -0
  307. package/dist/server/onboarding-html.js +169 -8
  308. package/dist/server/realtime-token.d.ts +1 -1
  309. package/dist/server/realtime-voice.js +1 -1
  310. package/dist/server/sentry.d.ts +1 -1
  311. package/dist/server/transcribe-voice.js +3 -3
  312. package/dist/shared/first-run-onboarding.d.ts +1 -0
  313. package/dist/shared/first-run-onboarding.js +1 -0
  314. package/dist/templates/chat/.agents/skills/agent-native-docs/SKILL.md +23 -3
  315. package/dist/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  316. package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +23 -2
  317. package/dist/templates/chat/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  318. package/dist/templates/chat/AGENTS.md +3 -0
  319. package/dist/templates/chat/DESIGN.md +28 -0
  320. package/dist/templates/chat/agent-native.json +12 -0
  321. package/dist/templates/default/.agents/skills/agent-native-docs/SKILL.md +23 -3
  322. package/dist/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  323. package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +23 -2
  324. package/dist/templates/default/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  325. package/dist/templates/default/AGENTS.md +4 -0
  326. package/dist/templates/default/DESIGN.md +30 -0
  327. package/dist/templates/default/agent-native.json +9 -0
  328. package/dist/templates/default/app/i18n/ar-SA.ts +2 -2
  329. package/dist/templates/default/app/i18n/de-DE.ts +2 -2
  330. package/dist/templates/default/app/i18n/en-US.ts +2 -2
  331. package/dist/templates/default/app/i18n/es-ES.ts +2 -2
  332. package/dist/templates/default/app/i18n/fr-FR.ts +2 -2
  333. package/dist/templates/default/app/i18n/hi-IN.ts +2 -2
  334. package/dist/templates/default/app/i18n/ja-JP.ts +2 -2
  335. package/dist/templates/default/app/i18n/ko-KR.ts +2 -2
  336. package/dist/templates/default/app/i18n/pt-BR.ts +2 -2
  337. package/dist/templates/default/app/i18n/zh-CN.ts +2 -2
  338. package/dist/templates/default/app/i18n/zh-TW.ts +1 -1
  339. package/dist/templates/default/package.json +1 -0
  340. package/dist/templates/headless/.agents/skills/agent-native-docs/SKILL.md +23 -3
  341. package/dist/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  342. package/dist/templates/headless/agent-native.json +9 -0
  343. package/dist/templates/headless/package.json +2 -0
  344. package/dist/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +23 -3
  345. package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  346. package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +23 -2
  347. package/dist/templates/workspace-core/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  348. package/dist/templates/workspace-core/AGENTS.md +3 -0
  349. package/dist/templates/workspace-core/DESIGN.md +35 -0
  350. package/dist/templates/workspace-root/AGENTS.md +3 -0
  351. package/dist/templates/workspace-root/DESIGN.md +35 -0
  352. package/dist/templates/workspace-root/agent-native.json +9 -0
  353. package/dist/templates/workspace-root/package.json +3 -0
  354. package/dist/transcription/builder-transcription.js +1 -1
  355. package/dist/user-profile/actions/change-password.d.ts +8 -0
  356. package/dist/user-profile/actions/change-password.js +24 -0
  357. package/dist/user-profile/actions/get-auth-methods.d.ts +6 -0
  358. package/dist/user-profile/actions/get-auth-methods.js +23 -0
  359. package/dist/user-profile/actions/set-password.d.ts +7 -0
  360. package/dist/user-profile/actions/set-password.js +23 -0
  361. package/dist/vite/client.d.ts +8 -1
  362. package/dist/vite/client.js +63 -12
  363. package/dist/vite/index.d.ts +1 -0
  364. package/dist/vite/index.js +1 -0
  365. package/docs/AGENTS.md +7 -2
  366. package/docs/SKILL.md +7 -5
  367. package/docs/content/agent-native-config.mdx +165 -0
  368. package/docs/content/agent-native-toolkit.mdx +1 -1
  369. package/docs/content/deployment.mdx +7 -2
  370. package/docs/content/doctor.mdx +21 -13
  371. package/docs/content/environment-variables.mdx +158 -0
  372. package/docs/content/file-uploads.mdx +1 -1
  373. package/docs/content/getting-started.mdx +1 -1
  374. package/docs/content/key-concepts.mdx +1 -1
  375. package/docs/content/multi-app-workspace.mdx +1 -1
  376. package/docs/content/template-clips-ai-and-editing.mdx +6 -6
  377. package/docs/content/template-clips-developers.mdx +3 -3
  378. package/docs/content/toolkit-settings.mdx +1 -1
  379. package/docs/content/voice-input.mdx +4 -4
  380. package/package.json +6 -2
  381. package/src/eject/provider-api-definitions.ts +1 -0
  382. package/src/eject/remote-mcp-presets.ts +1 -0
  383. package/src/templates/chat/.agents/skills/agent-native-docs/SKILL.md +23 -3
  384. package/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  385. package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +23 -2
  386. package/src/templates/chat/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  387. package/src/templates/chat/AGENTS.md +3 -0
  388. package/src/templates/chat/DESIGN.md +28 -0
  389. package/src/templates/chat/agent-native.json +12 -0
  390. package/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +23 -3
  391. package/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  392. package/src/templates/default/.agents/skills/frontend-design/SKILL.md +23 -2
  393. package/src/templates/default/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  394. package/src/templates/default/AGENTS.md +4 -0
  395. package/src/templates/default/DESIGN.md +30 -0
  396. package/src/templates/default/agent-native.json +9 -0
  397. package/src/templates/default/app/i18n/ar-SA.ts +2 -2
  398. package/src/templates/default/app/i18n/de-DE.ts +2 -2
  399. package/src/templates/default/app/i18n/en-US.ts +2 -2
  400. package/src/templates/default/app/i18n/es-ES.ts +2 -2
  401. package/src/templates/default/app/i18n/fr-FR.ts +2 -2
  402. package/src/templates/default/app/i18n/hi-IN.ts +2 -2
  403. package/src/templates/default/app/i18n/ja-JP.ts +2 -2
  404. package/src/templates/default/app/i18n/ko-KR.ts +2 -2
  405. package/src/templates/default/app/i18n/pt-BR.ts +2 -2
  406. package/src/templates/default/app/i18n/zh-CN.ts +2 -2
  407. package/src/templates/default/app/i18n/zh-TW.ts +1 -1
  408. package/src/templates/default/package.json +1 -0
  409. package/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +23 -3
  410. package/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  411. package/src/templates/headless/agent-native.json +9 -0
  412. package/src/templates/headless/package.json +2 -0
  413. package/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +23 -3
  414. package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  415. package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +23 -2
  416. package/src/templates/workspace-core/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  417. package/src/templates/workspace-core/AGENTS.md +3 -0
  418. package/src/templates/workspace-core/DESIGN.md +35 -0
  419. package/src/templates/workspace-root/AGENTS.md +3 -0
  420. package/src/templates/workspace-root/DESIGN.md +35 -0
  421. package/src/templates/workspace-root/agent-native.json +9 -0
  422. package/src/templates/workspace-root/package.json +3 -0
@@ -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.
@@ -506,7 +506,7 @@ export function transcriptStatusInstructions(
506
506
 
507
507
  if (status === "failed" && lowerReason.includes("credits exhausted")) {
508
508
  return [
509
- "Transcription failed because Builder transcription credits are exhausted. Tell the user to upgrade or connect Builder.io credits. Clips uses the browser/macOS native transcript first and Builder transcription on the original recording when native capture is unavailable.",
509
+ "Transcription failed because Builder transcription credits are exhausted. Tell the user to upgrade or connect Builder.io credits (free tier available). Clips uses the browser/macOS native transcript first and Builder transcription on the original recording when native capture is unavailable.",
510
510
  ];
511
511
  }
512
512
 
@@ -5,7 +5,7 @@ import {
5
5
  } from "@agent-native/core/server";
6
6
 
7
7
  export const STORAGE_SETUP_REQUIRED_REASON =
8
- "Video storage is not connected yet. Connect Builder.io or configure S3-compatible storage to upload clips.";
8
+ "Video storage is not connected yet. Connect Builder.io (free tier available) or configure S3-compatible storage to upload clips.";
9
9
 
10
10
  function appDatabaseUrl(): string {
11
11
  const appName = process.env.APP_NAME?.toUpperCase().replace(/-/g, "_");
@@ -931,6 +931,21 @@ const migrations = runMigrations(
931
931
  // guard:allow-unscoped — startup migration normalizes a legacy placeholder across all rows.
932
932
  sql: `UPDATE recording_agent_views SET agent_label = NULL WHERE agent_label = 'Agent'`,
933
933
  },
934
+ {
935
+ version: 58,
936
+ name: "recording-playback-positions",
937
+ sql: `CREATE TABLE IF NOT EXISTS recording_playback_positions (
938
+ id TEXT PRIMARY KEY,
939
+ recording_id TEXT NOT NULL,
940
+ viewer_key TEXT NOT NULL,
941
+ viewer_email TEXT,
942
+ position_ms INTEGER NOT NULL DEFAULT 0,
943
+ updated_at TEXT NOT NULL DEFAULT (datetime('now')),
944
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
945
+ );
946
+ CREATE UNIQUE INDEX IF NOT EXISTS recording_playback_positions_recording_viewer_key_unique_idx
947
+ ON recording_playback_positions (recording_id, viewer_key)`,
948
+ },
934
949
  ],
935
950
  { table: "clips_migrations" },
936
951
  );
@@ -26,7 +26,7 @@ import {
26
26
  const MAX_BYTES = 5 * 1024 * 1024;
27
27
 
28
28
  const STORAGE_SETUP_REQUIRED_REASON =
29
- "File storage is not connected yet. Connect Builder.io or configure S3-compatible storage in Settings → File uploads, then retry.";
29
+ "File storage is not connected yet. Connect Builder.io (free tier available) or configure S3-compatible storage in Settings → File uploads, then retry.";
30
30
 
31
31
  function randId(): string {
32
32
  const chars =
@@ -31,6 +31,26 @@ the framework monorepo checkout.
31
31
 
32
32
  From a generated app directory:
33
33
 
34
+ ```bash
35
+ pnpm action framework-search --pattern "defineAction"
36
+ pnpm action framework-search --pattern "templates/*/actions/*.ts" --mode glob --scope source
37
+ pnpm action framework-search --pattern "Agent(?:Panel|Sidebar)" --mode regex --scope source
38
+ ```
39
+
40
+ Use `framework-search` first when a question may cross the docs and source
41
+ boundary. It searches the version-matched framework docs, runtime-visible
42
+ skills, readable Core or Toolkit package source, and first-party template
43
+ corpus in one bounded read-only call. Use `scope: docs` or `scope: source` to
44
+ narrow it, then use the existing focused readers for the page or file you need.
45
+
46
+ The same tool is available in the headless `pnpm agent` loop and every built-in
47
+ app agent. Its default substring mode is safest for ordinary questions; use
48
+ `glob` for wildcard paths, `sql-like` for `%` and `_` wildcards, and `regex`
49
+ for precise structural matches. Results are bounded, so refine the pattern or
50
+ path instead of treating a truncated result as exhaustive.
51
+
52
+ From a generated app directory, the lower-level readers remain available:
53
+
34
54
  ```bash
35
55
  pnpm action docs-search --query "<feature>"
36
56
  pnpm action docs-search --slug <slug>
@@ -41,9 +61,9 @@ pnpm action source-search --path templates/chat/actions/hello.ts
41
61
  pnpm action source-search --list
42
62
  ```
43
63
 
44
- The headless `pnpm agent` loop and built-in app agent also expose a read-only
45
- `docs-search` tool with the same `query`, `slug`, and `list` options, plus a
46
- read-only `source-search` tool with `query`, `path`, and `list`.
64
+ The headless `pnpm agent` loop and built-in app agent also expose read-only
65
+ `framework-search`, `docs-search`, and `source-search` tools. Use the unified
66
+ tool for discovery, then the focused tools for full page or file reads.
47
67
 
48
68
  If the action runner is unavailable, search the package directly:
49
69
 
@@ -65,6 +65,22 @@ Contextual agent UI is not a reason to expose every option at once. Start with
65
65
  the domain task's primary action, reveal review or configuration only when the
66
66
  current state needs it, and let the sidebar carry conversational depth.
67
67
 
68
+ ## Visual Direction And Workspace Variety
69
+
70
+ Shared workspace behavior should be consistent without forcing every app into
71
+ the same visual skin. Keep shell and component tokens semantic, then let each
72
+ app declare a named direction in `DESIGN.md` before styling. A new app should
73
+ choose its palette family and composition from the product context, compare
74
+ nearby apps, and avoid inheriting their accent by default. Use the
75
+ `frontend-design` visual-direction reference for mode, palette, type, density,
76
+ shape, anti-references, and the `distill` / `typeset` / `colorize` / `layout` /
77
+ `polish` / `audit` review vocabulary.
78
+
79
+ Do not make warm beige plus terracotta the workspace fallback. Preserve a
80
+ workspace-level brand when one exists; otherwise keep shared chrome neutral and
81
+ allow app-owned accents to distinguish products while retaining accessible
82
+ semantic states and the shared AgentSidebar contract.
83
+
68
84
  ## Discover Before Building
69
85
 
70
86
  Before creating an app-local version of repeated workspace or agent UI:
@@ -234,6 +234,19 @@ Use `create-content-database`, `create-inline-content-database`,
234
234
  `duplicate-document-property`, and `delete-document-property`; do not edit
235
235
  property rows or view config via raw SQL when an action can do it.
236
236
 
237
+ For a bounded migration that must rewrite every existing row body while adding
238
+ new property definitions and values, use `migrate-content-database-rows` rather
239
+ than looping the single-row actions. Its `validate` phase is read-only; `apply`
240
+ commits the complete plan with an idempotency receipt or writes nothing. Read
241
+ the database and every row independently after apply, then call its separate
242
+ `verify` phase with the saved post-apply digest. Only a verified receipt may
243
+ `finalize` the exact legacy property IDs stored in that receipt. `rollback` is
244
+ available before finalize only while the saved post-apply digest still matches,
245
+ so it never overwrites a later edit. The bounded migration accepts ordinary
246
+ databases without attached Sources; source-backed and system databases retain
247
+ their dedicated synchronization actions. If flushing a live row editor changes
248
+ its persisted revision, read the rows again and build a fresh plan.
249
+
237
250
  When targeting more than one database row, call `duplicate-database-items` or
238
251
  `remove-database-items` once with a native JSON array of `itemIds` or
239
252
  `documentIds`. Do not loop `duplicate-database-item` or `delete-document` for