@agent-native/core 0.137.7 → 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 (446) 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/components/recorder/pre-record-panel.tsx +65 -18
  66. package/corpus/templates/clips/app/hooks/use-playback-position.ts +188 -0
  67. package/corpus/templates/clips/app/hooks/use-view-tracking.ts +6 -24
  68. package/corpus/templates/clips/app/i18n/en-US.ts +4 -0
  69. package/corpus/templates/clips/app/lib/playback-position.ts +99 -0
  70. package/corpus/templates/clips/app/lib/viewer-session.ts +29 -0
  71. package/corpus/templates/clips/changelog/2026-08-05-clip-buffering-now-uses-buffering-copy-after-playback.md +6 -0
  72. package/corpus/templates/clips/changelog/2026-08-05-clips-remembers-your-playback-position-when-you-reopen-a-cli.md +6 -0
  73. package/corpus/templates/clips/desktop/package.json +1 -0
  74. package/corpus/templates/clips/desktop/src/app.tsx +70 -6
  75. package/corpus/templates/clips/desktop/src/components/AlertDialog.tsx +131 -0
  76. package/corpus/templates/clips/desktop/src/styles.css +129 -0
  77. package/corpus/templates/clips/learnings.defaults.md +1 -1
  78. package/corpus/templates/clips/server/db/schema.ts +18 -0
  79. package/corpus/templates/clips/server/lib/public-agent-context.ts +1 -1
  80. package/corpus/templates/clips/server/lib/video-storage.ts +1 -1
  81. package/corpus/templates/clips/server/plugins/db.ts +15 -0
  82. package/corpus/templates/clips/server/routes/api/media/index.post.ts +1 -1
  83. package/corpus/templates/content/.agents/skills/agent-native-docs/SKILL.md +23 -3
  84. package/corpus/templates/content/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  85. package/corpus/templates/content/.agents/skills/document-editing/references/databases.md +13 -0
  86. package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +23 -2
  87. package/corpus/templates/content/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  88. package/corpus/templates/content/AGENTS.md +1 -0
  89. package/corpus/templates/content/actions/_content-database-mutation-lock.ts +41 -0
  90. package/corpus/templates/content/actions/_content-database-row-migration.ts +569 -0
  91. package/corpus/templates/content/actions/_database-source-utils.ts +82 -36
  92. package/corpus/templates/content/actions/_database-utils.ts +5 -0
  93. package/corpus/templates/content/actions/_delete-content-space.ts +25 -11
  94. package/corpus/templates/content/actions/add-database-item.ts +60 -42
  95. package/corpus/templates/content/actions/attach-content-database-source.ts +2 -0
  96. package/corpus/templates/content/actions/configure-document-property.ts +99 -104
  97. package/corpus/templates/content/actions/delete-content-database.ts +19 -7
  98. package/corpus/templates/content/actions/delete-document-property.ts +47 -58
  99. package/corpus/templates/content/actions/delete-document.ts +390 -167
  100. package/corpus/templates/content/actions/disconnect-content-database-source.ts +41 -24
  101. package/corpus/templates/content/actions/duplicate-database-item.ts +63 -31
  102. package/corpus/templates/content/actions/duplicate-database-items.ts +86 -43
  103. package/corpus/templates/content/actions/duplicate-document-property.ts +37 -14
  104. package/corpus/templates/content/actions/migrate-content-database-rows.ts +830 -0
  105. package/corpus/templates/content/actions/move-database-item.ts +14 -0
  106. package/corpus/templates/content/actions/permanently-delete-document.ts +27 -6
  107. package/corpus/templates/content/actions/remove-database-items.ts +13 -0
  108. package/corpus/templates/content/actions/reorder-document-property.ts +45 -46
  109. package/corpus/templates/content/actions/set-document-property.ts +68 -28
  110. package/corpus/templates/content/actions/submit-content-database-form.ts +49 -0
  111. package/corpus/templates/content/actions/transcribe-media.ts +1 -1
  112. package/corpus/templates/content/agent-native.json +12 -0
  113. package/corpus/templates/content/app/components/editor/image-upload.ts +2 -2
  114. package/corpus/templates/content/app/i18n-data.ts +1 -1
  115. package/corpus/templates/content/changelog/2026-08-01-content-can-reorganize-every-row-in-an-existing-database-as-.md +6 -0
  116. package/corpus/templates/content/parity/matrix.md +1 -1
  117. package/corpus/templates/content/parity/matrix.ts +4 -2
  118. package/corpus/templates/content/server/db/schema.ts +30 -0
  119. package/corpus/templates/content/server/plugins/db.ts +24 -0
  120. package/corpus/templates/content/server/plugins/onboarding.ts +2 -2
  121. package/corpus/templates/crm/.agents/skills/agent-native-docs/SKILL.md +23 -3
  122. package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  123. package/corpus/templates/crm/agent-native.json +12 -0
  124. package/corpus/templates/design/.agents/skills/agent-native-docs/SKILL.md +23 -3
  125. package/corpus/templates/design/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  126. package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +2 -0
  127. package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +23 -2
  128. package/corpus/templates/design/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  129. package/corpus/templates/design/CODE_NATIVE_DESIGN_STUDIO_IMPLEMENTATION_PLAN.md +2 -2
  130. package/corpus/templates/design/DESIGN-STUDIO-PLAN.md +2 -2
  131. package/corpus/templates/design/actions/apply-design-token-edit.ts +1 -1
  132. package/corpus/templates/design/actions/capture-design-state.ts +1 -1
  133. package/corpus/templates/design/actions/connect-builder-app.ts +2 -2
  134. package/corpus/templates/design/actions/create-design-branch.ts +1 -1
  135. package/corpus/templates/design/actions/create-fusion-app.ts +3 -3
  136. package/corpus/templates/design/actions/deploy-design-preview.ts +1 -1
  137. package/corpus/templates/design/actions/generate-design.ts +3 -2
  138. package/corpus/templates/design/actions/get-component-details.ts +1 -1
  139. package/corpus/templates/design/actions/get-design-branch-diff.ts +1 -1
  140. package/corpus/templates/design/actions/index-components.ts +3 -3
  141. package/corpus/templates/design/actions/index-design-system-with-builder.ts +1 -1
  142. package/corpus/templates/design/actions/migrate-inline-design-to-app.ts +3 -3
  143. package/corpus/templates/design/actions/open-component-source.ts +1 -1
  144. package/corpus/templates/design/actions/update-design.ts +96 -14
  145. package/corpus/templates/design/agent-native.json +12 -0
  146. package/corpus/templates/design/app/components/design/DesignImportPanel.tsx +7 -2
  147. package/corpus/templates/design/app/components/design/FigmaHydrationDialog.tsx +11 -2
  148. package/corpus/templates/design/app/components/design/edit-panel/component-section.tsx +1 -1
  149. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +8 -1
  150. package/corpus/templates/design/app/i18n-data.ts +53 -22
  151. package/corpus/templates/design/app/lib/design-file-upload.ts +2 -3
  152. package/corpus/templates/design/app/lib/upload-limits.ts +4 -0
  153. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +1 -1
  154. package/corpus/templates/design/changelog/2026-08-05-chat-attachments-now-warn-before-upload-when-they-exceed-the.md +6 -0
  155. package/corpus/templates/design/changelog/2026-08-05-figma-fig-uploads-now-show-a-clear-4-mb-limit-up-front-inste.md +6 -0
  156. package/corpus/templates/design/scripts/qa-figma-stress-import.ts +1 -1
  157. package/corpus/templates/design/server/handlers/import-design-file.ts +9 -5
  158. package/corpus/templates/design/server/handlers/uploads.ts +13 -9
  159. package/corpus/templates/design/server/lib/fig-file-limits.ts +2 -1
  160. package/corpus/templates/design/server/lib/figma-image-hydration.ts +1 -1
  161. package/corpus/templates/design/server/lib/figma-node-import.ts +1 -1
  162. package/corpus/templates/design/server/lib/request-body-limits.ts +11 -0
  163. package/corpus/templates/design/shared/canvas-frames.ts +81 -0
  164. package/corpus/templates/design/shared/design-source-capabilities.ts +25 -9
  165. package/corpus/templates/dispatch/.agents/skills/agent-native-docs/SKILL.md +23 -3
  166. package/corpus/templates/dispatch/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  167. package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +23 -2
  168. package/corpus/templates/dispatch/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  169. package/corpus/templates/dispatch/agent-native.json +12 -0
  170. package/corpus/templates/factory/.agents/skills/agent-native-docs/SKILL.md +23 -3
  171. package/corpus/templates/factory/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  172. package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +23 -2
  173. package/corpus/templates/factory/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  174. package/corpus/templates/factory/agent-native.json +12 -0
  175. package/corpus/templates/forms/.agents/skills/agent-native-docs/SKILL.md +23 -3
  176. package/corpus/templates/forms/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  177. package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +23 -2
  178. package/corpus/templates/forms/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  179. package/corpus/templates/forms/actions/export-responses.ts +1 -1
  180. package/corpus/templates/forms/agent-native.json +12 -0
  181. package/corpus/templates/macros/.agents/skills/agent-native-docs/SKILL.md +23 -3
  182. package/corpus/templates/macros/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  183. package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +23 -2
  184. package/corpus/templates/macros/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  185. package/corpus/templates/macros/agent-native.json +12 -0
  186. package/corpus/templates/mail/.agents/skills/agent-native-docs/SKILL.md +23 -3
  187. package/corpus/templates/mail/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  188. package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +23 -2
  189. package/corpus/templates/mail/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  190. package/corpus/templates/mail/agent-native.json +12 -0
  191. package/corpus/templates/mail/app/i18n/en-US.ts +1 -1
  192. package/corpus/templates/mail/server/lib/media-upload.ts +1 -1
  193. package/corpus/templates/plan/.agents/skills/agent-native-docs/SKILL.md +23 -3
  194. package/corpus/templates/plan/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  195. package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +23 -2
  196. package/corpus/templates/plan/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  197. package/corpus/templates/plan/agent-native.json +12 -0
  198. package/corpus/templates/plan/server/lib/plan-assets.ts +1 -1
  199. package/corpus/templates/slides/.agents/skills/agent-native-docs/SKILL.md +23 -3
  200. package/corpus/templates/slides/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  201. package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +23 -2
  202. package/corpus/templates/slides/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  203. package/corpus/templates/slides/actions/generate-image-api.ts +1 -1
  204. package/corpus/templates/slides/actions/generate-slides-ai.ts +1 -1
  205. package/corpus/templates/slides/actions/import-file.ts +2 -2
  206. package/corpus/templates/slides/actions/index-design-system-with-builder.ts +1 -1
  207. package/corpus/templates/slides/agent-native.json +12 -0
  208. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +1 -1
  209. package/corpus/templates/slides/app/i18n/en-US.ts +2 -2
  210. package/corpus/templates/slides/app/lib/deck-sorting.ts +19 -0
  211. package/corpus/templates/slides/app/lib/image-drop-to-agent.ts +1 -1
  212. package/corpus/templates/slides/app/pages/Index.tsx +7 -2
  213. package/corpus/templates/slides/changelog/2026-08-05-decks-are-now-sorted-by-most-recently-updated.md +6 -0
  214. package/corpus/templates/slides/server/handlers/assets.ts +1 -1
  215. package/corpus/templates/slides/server/handlers/uploads.ts +1 -1
  216. package/corpus/templates/tasks/.agents/skills/agent-native-docs/SKILL.md +23 -3
  217. package/corpus/templates/tasks/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  218. package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +23 -2
  219. package/corpus/templates/tasks/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  220. package/corpus/templates/tasks/agent-native.json +12 -0
  221. package/dist/action.d.ts +6 -0
  222. package/dist/agent/engine/builder-engine.js +2 -2
  223. package/dist/agent/engine/credential-errors.d.ts +1 -1
  224. package/dist/agent/engine/credential-errors.js +2 -2
  225. package/dist/agent/production-agent.js +3 -2
  226. package/dist/brand-kit/fig/index.js +1 -1
  227. package/dist/cli/agent.js +45 -3
  228. package/dist/cli/code-agent-executor.js +2 -1
  229. package/dist/cli/create.d.ts +9 -1
  230. package/dist/cli/create.js +94 -1
  231. package/dist/cli/doctor.d.ts +8 -11
  232. package/dist/cli/doctor.js +92 -24
  233. package/dist/cli/index.js +6 -5
  234. package/dist/client/AgentAskPopover.d.ts +3 -1
  235. package/dist/client/AgentAskPopover.js +2 -2
  236. package/dist/client/AgentPanel.js +9 -3
  237. package/dist/client/AssistantChat.js +54 -33
  238. package/dist/client/MultiTabAssistantChat.js +1 -1
  239. package/dist/client/RouteTransitionIndicator.d.ts +7 -0
  240. package/dist/client/RouteTransitionIndicator.js +31 -0
  241. package/dist/client/agent-engine-key.js +1 -1
  242. package/dist/client/app-providers.js +11 -2
  243. package/dist/client/chat/message-components.js +1 -1
  244. package/dist/client/chat/run-recovery.js +1 -1
  245. package/dist/client/chat/tool-call-display.d.ts +3 -1
  246. package/dist/client/chat/tool-call-display.js +4 -3
  247. package/dist/client/chat-model-groups.d.ts +6 -0
  248. package/dist/client/chat-model-groups.js +11 -0
  249. package/dist/client/error-format.js +1 -1
  250. package/dist/client/i18n.js +1 -1
  251. package/dist/client/onboarding/FirstRunOnboarding.d.ts +5 -1
  252. package/dist/client/onboarding/FirstRunOnboarding.js +29 -13
  253. package/dist/client/onboarding/first-run-enabled.d.ts +6 -1
  254. package/dist/client/onboarding/first-run-enabled.js +33 -3
  255. package/dist/client/onboarding/use-onboarding.js +16 -11
  256. package/dist/client/require-session.js +13 -4
  257. package/dist/client/resources/mcp-integration-catalog.js +26 -0
  258. package/dist/client/resources/mcp-integration-logos.js +4 -0
  259. package/dist/client/route-warmup.js +56 -10
  260. package/dist/client/settings/AccountSettingsCard.js +78 -3
  261. package/dist/client/settings/SettingsPanel.js +1 -1
  262. package/dist/client/settings/VoiceTranscriptionSection.js +2 -2
  263. package/dist/client/settings/useBuilderStatus.js +1 -1
  264. package/dist/client/setup-connections/useBuilderConnectCardController.js +1 -1
  265. package/dist/client/ui/index.d.ts +1 -0
  266. package/dist/client/ui/index.js +1 -0
  267. package/dist/client/uploads/upload-editor-image.js +1 -1
  268. package/dist/client/use-chat-threads.js +3 -0
  269. package/dist/client/use-session.d.ts +11 -0
  270. package/dist/client/use-session.js +34 -6
  271. package/dist/collab/routes.d.ts +2 -2
  272. package/dist/config.d.ts +48 -0
  273. package/dist/config.js +111 -0
  274. package/dist/db/migrations.js +5 -0
  275. package/dist/eject/provider-api-definitions.d.ts +1 -1
  276. package/dist/eject/provider-api-definitions.js +1 -0
  277. package/dist/eject/remote-mcp-presets.js +1 -0
  278. package/dist/extensions/web-search-tool.js +2 -2
  279. package/dist/file-upload/actions/upload-image.js +1 -1
  280. package/dist/file-upload/registry.js +1 -1
  281. package/dist/guards/index.d.ts +3 -0
  282. package/dist/guards/index.js +2 -0
  283. package/dist/guards/no-empty-migrations.d.ts +14 -0
  284. package/dist/guards/no-empty-migrations.js +126 -0
  285. package/dist/index.browser.d.ts +1 -0
  286. package/dist/index.browser.js +3 -0
  287. package/dist/index.d.ts +1 -0
  288. package/dist/index.js +1 -0
  289. package/dist/localization/default-messages.d.ts +24 -0
  290. package/dist/localization/default-messages.js +26 -2
  291. package/dist/notifications/routes.d.ts +6 -6
  292. package/dist/onboarding/app-profile.js +1 -1
  293. package/dist/onboarding/plugin.d.ts +2 -0
  294. package/dist/onboarding/plugin.js +29 -2
  295. package/dist/progress/routes.d.ts +1 -1
  296. package/dist/provider-api/actions/custom-provider-registration.d.ts +16 -16
  297. package/dist/provider-api/actions/provider-api.d.ts +13 -13
  298. package/dist/provider-api/index.d.ts +4 -4
  299. package/dist/provider-api/index.js +35 -0
  300. package/dist/resources/handlers.d.ts +1 -1
  301. package/dist/resources/handlers.js +1 -1
  302. package/dist/scripts/docs/framework-search.d.ts +9 -0
  303. package/dist/scripts/docs/framework-search.js +239 -0
  304. package/dist/scripts/docs/index.js +1 -0
  305. package/dist/scripts/docs/search.d.ts +10 -0
  306. package/dist/scripts/docs/search.js +1 -1
  307. package/dist/scripts/docs/source-search.d.ts +10 -2
  308. package/dist/scripts/docs/source-search.js +108 -41
  309. package/dist/search-utils/index.d.ts +11 -0
  310. package/dist/search-utils/index.js +72 -0
  311. package/dist/server/action-change.d.ts +6 -0
  312. package/dist/server/action-change.js +28 -14
  313. package/dist/server/action-discovery.js +9 -0
  314. package/dist/server/action-routes.js +1 -0
  315. package/dist/server/agent-chat/browser-team-tools.js +1 -1
  316. package/dist/server/agent-chat/script-entries.js +43 -2
  317. package/dist/server/auth-login-mode.d.ts +8 -0
  318. package/dist/server/auth-login-mode.js +17 -0
  319. package/dist/server/auth.js +100 -15
  320. package/dist/server/better-auth-instance.d.ts +36 -0
  321. package/dist/server/better-auth-instance.js +25 -3
  322. package/dist/server/builder-design-systems.js +1 -1
  323. package/dist/server/core-routes-plugin.js +17 -14
  324. package/dist/server/credential-provider.js +3 -3
  325. package/dist/server/email-templates.d.ts +7 -0
  326. package/dist/server/email-templates.js +24 -0
  327. package/dist/server/email.d.ts +17 -0
  328. package/dist/server/email.js +22 -1
  329. package/dist/server/framework-request-handler.js +6 -0
  330. package/dist/server/onboarding-html.d.ts +2 -0
  331. package/dist/server/onboarding-html.js +169 -8
  332. package/dist/server/realtime-token.d.ts +1 -1
  333. package/dist/server/realtime-voice.js +1 -1
  334. package/dist/server/sentry.d.ts +1 -1
  335. package/dist/server/transcribe-voice.js +3 -3
  336. package/dist/shared/first-run-onboarding.d.ts +1 -0
  337. package/dist/shared/first-run-onboarding.js +1 -0
  338. package/dist/templates/chat/.agents/skills/agent-native-docs/SKILL.md +23 -3
  339. package/dist/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  340. package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +23 -2
  341. package/dist/templates/chat/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  342. package/dist/templates/chat/AGENTS.md +3 -0
  343. package/dist/templates/chat/DESIGN.md +28 -0
  344. package/dist/templates/chat/agent-native.json +12 -0
  345. package/dist/templates/default/.agents/skills/agent-native-docs/SKILL.md +23 -3
  346. package/dist/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  347. package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +23 -2
  348. package/dist/templates/default/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  349. package/dist/templates/default/AGENTS.md +4 -0
  350. package/dist/templates/default/DESIGN.md +30 -0
  351. package/dist/templates/default/agent-native.json +9 -0
  352. package/dist/templates/default/app/i18n/ar-SA.ts +2 -2
  353. package/dist/templates/default/app/i18n/de-DE.ts +2 -2
  354. package/dist/templates/default/app/i18n/en-US.ts +2 -2
  355. package/dist/templates/default/app/i18n/es-ES.ts +2 -2
  356. package/dist/templates/default/app/i18n/fr-FR.ts +2 -2
  357. package/dist/templates/default/app/i18n/hi-IN.ts +2 -2
  358. package/dist/templates/default/app/i18n/ja-JP.ts +2 -2
  359. package/dist/templates/default/app/i18n/ko-KR.ts +2 -2
  360. package/dist/templates/default/app/i18n/pt-BR.ts +2 -2
  361. package/dist/templates/default/app/i18n/zh-CN.ts +2 -2
  362. package/dist/templates/default/app/i18n/zh-TW.ts +1 -1
  363. package/dist/templates/default/package.json +1 -0
  364. package/dist/templates/headless/.agents/skills/agent-native-docs/SKILL.md +23 -3
  365. package/dist/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  366. package/dist/templates/headless/agent-native.json +9 -0
  367. package/dist/templates/headless/package.json +2 -0
  368. package/dist/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +23 -3
  369. package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  370. package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +23 -2
  371. package/dist/templates/workspace-core/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  372. package/dist/templates/workspace-core/AGENTS.md +3 -0
  373. package/dist/templates/workspace-core/DESIGN.md +35 -0
  374. package/dist/templates/workspace-root/AGENTS.md +3 -0
  375. package/dist/templates/workspace-root/DESIGN.md +35 -0
  376. package/dist/templates/workspace-root/agent-native.json +9 -0
  377. package/dist/templates/workspace-root/package.json +3 -0
  378. package/dist/transcription/builder-transcription.js +1 -1
  379. package/dist/user-profile/actions/change-password.d.ts +8 -0
  380. package/dist/user-profile/actions/change-password.js +24 -0
  381. package/dist/user-profile/actions/get-auth-methods.d.ts +6 -0
  382. package/dist/user-profile/actions/get-auth-methods.js +23 -0
  383. package/dist/user-profile/actions/set-password.d.ts +7 -0
  384. package/dist/user-profile/actions/set-password.js +23 -0
  385. package/dist/vite/client.d.ts +8 -1
  386. package/dist/vite/client.js +63 -12
  387. package/dist/vite/index.d.ts +1 -0
  388. package/dist/vite/index.js +1 -0
  389. package/docs/AGENTS.md +7 -2
  390. package/docs/SKILL.md +7 -5
  391. package/docs/content/agent-native-config.mdx +165 -0
  392. package/docs/content/agent-native-toolkit.mdx +1 -1
  393. package/docs/content/deployment.mdx +7 -2
  394. package/docs/content/doctor.mdx +21 -13
  395. package/docs/content/environment-variables.mdx +158 -0
  396. package/docs/content/file-uploads.mdx +1 -1
  397. package/docs/content/getting-started.mdx +1 -1
  398. package/docs/content/key-concepts.mdx +1 -1
  399. package/docs/content/multi-app-workspace.mdx +1 -1
  400. package/docs/content/template-clips-ai-and-editing.mdx +6 -6
  401. package/docs/content/template-clips-developers.mdx +3 -3
  402. package/docs/content/toolkit-settings.mdx +1 -1
  403. package/docs/content/voice-input.mdx +4 -4
  404. package/package.json +6 -2
  405. package/src/eject/provider-api-definitions.ts +1 -0
  406. package/src/eject/remote-mcp-presets.ts +1 -0
  407. package/src/templates/chat/.agents/skills/agent-native-docs/SKILL.md +23 -3
  408. package/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  409. package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +23 -2
  410. package/src/templates/chat/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  411. package/src/templates/chat/AGENTS.md +3 -0
  412. package/src/templates/chat/DESIGN.md +28 -0
  413. package/src/templates/chat/agent-native.json +12 -0
  414. package/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +23 -3
  415. package/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  416. package/src/templates/default/.agents/skills/frontend-design/SKILL.md +23 -2
  417. package/src/templates/default/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  418. package/src/templates/default/AGENTS.md +4 -0
  419. package/src/templates/default/DESIGN.md +30 -0
  420. package/src/templates/default/agent-native.json +9 -0
  421. package/src/templates/default/app/i18n/ar-SA.ts +2 -2
  422. package/src/templates/default/app/i18n/de-DE.ts +2 -2
  423. package/src/templates/default/app/i18n/en-US.ts +2 -2
  424. package/src/templates/default/app/i18n/es-ES.ts +2 -2
  425. package/src/templates/default/app/i18n/fr-FR.ts +2 -2
  426. package/src/templates/default/app/i18n/hi-IN.ts +2 -2
  427. package/src/templates/default/app/i18n/ja-JP.ts +2 -2
  428. package/src/templates/default/app/i18n/ko-KR.ts +2 -2
  429. package/src/templates/default/app/i18n/pt-BR.ts +2 -2
  430. package/src/templates/default/app/i18n/zh-CN.ts +2 -2
  431. package/src/templates/default/app/i18n/zh-TW.ts +1 -1
  432. package/src/templates/default/package.json +1 -0
  433. package/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +23 -3
  434. package/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  435. package/src/templates/headless/agent-native.json +9 -0
  436. package/src/templates/headless/package.json +2 -0
  437. package/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +23 -3
  438. package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  439. package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +23 -2
  440. package/src/templates/workspace-core/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  441. package/src/templates/workspace-core/AGENTS.md +3 -0
  442. package/src/templates/workspace-core/DESIGN.md +35 -0
  443. package/src/templates/workspace-root/AGENTS.md +3 -0
  444. package/src/templates/workspace-root/DESIGN.md +35 -0
  445. package/src/templates/workspace-root/agent-native.json +9 -0
  446. package/src/templates/workspace-root/package.json +3 -0
@@ -5,6 +5,10 @@ import { and, asc, eq, inArray, isNull, sql } from "drizzle-orm";
5
5
  import { z } from "zod";
6
6
 
7
7
  import { getDb, schema } from "../server/db/index.js";
8
+ import {
9
+ lockContentDatabaseMutation,
10
+ touchContentDatabase,
11
+ } from "./_content-database-mutation-lock.js";
8
12
  import { getContentDatabaseResponse } from "./_database-utils.js";
9
13
  import {
10
14
  databaseItemsPositionScope,
@@ -69,6 +73,11 @@ export default defineAction({
69
73
  databaseItemsPositionScope(row.item.databaseId),
70
74
  () =>
71
75
  db.transaction(async (tx) => {
76
+ await lockContentDatabaseMutation(
77
+ tx as unknown as ReturnType<typeof getDb>,
78
+ row.item.databaseId,
79
+ );
80
+
72
81
  const items = await tx
73
82
  .select()
74
83
  .from(schema.contentDatabaseItems)
@@ -88,6 +97,11 @@ export default defineAction({
88
97
  const [moved] = nextItems.splice(currentIndex, 1);
89
98
  nextItems.splice(nextIndex, 0, moved);
90
99
  const now = new Date().toISOString();
100
+ await touchContentDatabase(
101
+ tx as unknown as ReturnType<typeof getDb>,
102
+ row.item.databaseId,
103
+ now,
104
+ );
91
105
  const itemIds = nextItems.map((item) => item.id);
92
106
  const documentIds = nextItems.map((item) => item.documentId);
93
107
 
@@ -4,7 +4,12 @@ import { assertAccess } from "@agent-native/core/sharing";
4
4
  import { z } from "zod";
5
5
 
6
6
  import { getDb } from "../server/db/index.js";
7
- import { deleteTrashedDocumentSubtree } from "./delete-document.js";
7
+ import {
8
+ deleteTrashedDocumentSubtree,
9
+ PermanentDeleteScopeChangedError,
10
+ } from "./delete-document.js";
11
+
12
+ const MAX_DELETE_SCOPE_ATTEMPTS = 3;
8
13
 
9
14
  export default defineAction({
10
15
  description:
@@ -15,11 +20,27 @@ export default defineAction({
15
20
  run: async ({ id }) => {
16
21
  const access = await assertAccess("document", id, "admin");
17
22
  const db = getDb();
18
- const deleted = await deleteTrashedDocumentSubtree(
19
- db,
20
- id,
21
- access.resource.ownerEmail as string,
22
- );
23
+ let deleted: string[] | undefined;
24
+ for (let attempt = 1; attempt <= MAX_DELETE_SCOPE_ATTEMPTS; attempt += 1) {
25
+ try {
26
+ deleted = await db.transaction((tx) =>
27
+ deleteTrashedDocumentSubtree(
28
+ tx as unknown as ReturnType<typeof getDb>,
29
+ id,
30
+ access.resource.ownerEmail as string,
31
+ ),
32
+ );
33
+ break;
34
+ } catch (error) {
35
+ if (
36
+ !(error instanceof PermanentDeleteScopeChangedError) ||
37
+ attempt === MAX_DELETE_SCOPE_ATTEMPTS
38
+ ) {
39
+ throw error;
40
+ }
41
+ }
42
+ }
43
+ if (!deleted) throw new Error("Document deletion did not complete.");
23
44
  await writeAppState("refresh-signal", { ts: Date.now() });
24
45
  return { success: true, deleted: deleted.length };
25
46
  },
@@ -4,6 +4,10 @@ import { assertAccess } from "@agent-native/core/sharing";
4
4
  import { and, eq, inArray } from "drizzle-orm";
5
5
 
6
6
  import { getDb, schema } from "../server/db/index.js";
7
+ import {
8
+ lockContentDatabaseMutation,
9
+ touchContentDatabase,
10
+ } from "./_content-database-mutation-lock.js";
7
11
  import { assertNotWorkspaceCatalogDocuments } from "./_content-space-catalog-guards.js";
8
12
  import { lockDatabaseMemberships } from "./_database-membership-lock.js";
9
13
  import {
@@ -80,6 +84,15 @@ export default defineAction({
80
84
 
81
85
  await withPositionLock(databaseItemsPositionScope(database.id), () =>
82
86
  db.transaction(async (tx) => {
87
+ await lockContentDatabaseMutation(
88
+ tx as unknown as ReturnType<typeof getDb>,
89
+ database.id,
90
+ );
91
+ await touchContentDatabase(
92
+ tx as unknown as ReturnType<typeof getDb>,
93
+ database.id,
94
+ now,
95
+ );
83
96
  if (removedItemIds.length > 0) {
84
97
  await lockDatabaseMemberships(tx, removedItemIds);
85
98
  const [sourceRow, hydrationRow] = await Promise.all([
@@ -5,6 +5,7 @@ import { and, asc, eq } from "drizzle-orm";
5
5
  import { z } from "zod";
6
6
 
7
7
  import { getDb, schema } from "../server/db/index.js";
8
+ import { lockContentDatabaseMutation } from "./_content-database-mutation-lock.js";
8
9
  import {
9
10
  listPropertiesForDocument,
10
11
  resolvePropertyDatabaseForDocument,
@@ -45,54 +46,52 @@ export default defineAction({
45
46
  );
46
47
  if (!database) throw new Error("Document is not part of a database.");
47
48
 
48
- const definitions = await db
49
- .select()
50
- .from(schema.documentPropertyDefinitions)
51
- .where(eq(schema.documentPropertyDefinitions.databaseId, database.id))
52
- .orderBy(asc(schema.documentPropertyDefinitions.position));
53
-
54
- const ids = definitions.map((definition) => definition.id);
55
- if (!ids.includes(propertyId)) {
56
- throw new Error(`Property "${propertyId}" not found`);
57
- }
58
- if (!ids.includes(targetPropertyId)) {
59
- throw new Error(`Property "${targetPropertyId}" not found`);
60
- }
61
- const definitionById = new Map(
62
- definitions.map((definition) => [definition.id, definition]),
63
- );
64
- if (
65
- definitionById.get(propertyId)?.systemRole ||
66
- definitionById.get(targetPropertyId)?.systemRole
67
- ) {
68
- throw new Error("System properties cannot be reordered.");
69
- }
70
- if (propertyId === targetPropertyId) {
71
- return {
72
- documentId,
73
- databaseId: database.id,
74
- properties: await listPropertiesForDocument(document, database.id),
75
- };
76
- }
49
+ const now = new Date().toISOString();
50
+ await db.transaction(async (tx) => {
51
+ await lockContentDatabaseMutation(
52
+ tx as unknown as ReturnType<typeof getDb>,
53
+ database.id,
54
+ );
55
+ const definitions = await tx
56
+ .select()
57
+ .from(schema.documentPropertyDefinitions)
58
+ .where(eq(schema.documentPropertyDefinitions.databaseId, database.id))
59
+ .orderBy(asc(schema.documentPropertyDefinitions.position));
60
+ const ids = definitions.map((definition) => definition.id);
61
+ if (!ids.includes(propertyId)) {
62
+ throw new Error(`Property "${propertyId}" not found`);
63
+ }
64
+ if (!ids.includes(targetPropertyId)) {
65
+ throw new Error(`Property "${targetPropertyId}" not found`);
66
+ }
67
+ const definitionById = new Map(
68
+ definitions.map((definition) => [definition.id, definition]),
69
+ );
70
+ if (
71
+ definitionById.get(propertyId)?.systemRole ||
72
+ definitionById.get(targetPropertyId)?.systemRole
73
+ ) {
74
+ throw new Error("System properties cannot be reordered.");
75
+ }
76
+ if (propertyId === targetPropertyId) return;
77
77
 
78
- // Rebuild the order with the moved property re-inserted relative to target.
79
- const remaining = ids.filter((id) => id !== propertyId);
80
- const targetIndex = remaining.indexOf(targetPropertyId);
81
- const insertAt = position === "after" ? targetIndex + 1 : targetIndex;
82
- remaining.splice(insertAt, 0, propertyId);
78
+ const remaining = ids.filter((id) => id !== propertyId);
79
+ const targetIndex = remaining.indexOf(targetPropertyId);
80
+ const insertAt = position === "after" ? targetIndex + 1 : targetIndex;
81
+ remaining.splice(insertAt, 0, propertyId);
83
82
 
84
- const now = new Date().toISOString();
85
- for (let index = 0; index < remaining.length; index += 1) {
86
- await db
87
- .update(schema.documentPropertyDefinitions)
88
- .set({ position: index, updatedAt: now })
89
- .where(
90
- and(
91
- eq(schema.documentPropertyDefinitions.id, remaining[index]),
92
- eq(schema.documentPropertyDefinitions.databaseId, database.id),
93
- ),
94
- );
95
- }
83
+ for (let index = 0; index < remaining.length; index += 1) {
84
+ await tx
85
+ .update(schema.documentPropertyDefinitions)
86
+ .set({ position: index, updatedAt: now })
87
+ .where(
88
+ and(
89
+ eq(schema.documentPropertyDefinitions.id, remaining[index]),
90
+ eq(schema.documentPropertyDefinitions.databaseId, database.id),
91
+ ),
92
+ );
93
+ }
94
+ });
96
95
 
97
96
  await writeAppState("refresh-signal", { ts: Date.now() });
98
97
 
@@ -1,6 +1,6 @@
1
1
  import { defineAction } from "@agent-native/core";
2
2
  import { assertAccess } from "@agent-native/core/sharing";
3
- import { and, eq, isNull, ne, sql } from "drizzle-orm";
3
+ import { and, eq, isNull, ne } from "drizzle-orm";
4
4
  import { z } from "zod";
5
5
 
6
6
  import { getDb, schema } from "../server/db/index.js";
@@ -12,6 +12,7 @@ import {
12
12
  parsePropertyOptions,
13
13
  type DocumentPropertyType,
14
14
  } from "../shared/properties.js";
15
+ import { lockContentDatabaseMutation } from "./_content-database-mutation-lock.js";
15
16
  import { resolveContentDocumentAccess } from "./_content-document-access.js";
16
17
  import { lockDatabaseMemberships } from "./_database-membership-lock.js";
17
18
  import {
@@ -80,11 +81,41 @@ export default defineAction({
80
81
  await assertAccess("document", documentId, "editor");
81
82
  const normalized = normalizePropertyValue(type, value);
82
83
  const content = typeof normalized === "string" ? normalized : "";
83
- const target = blocksStorageTarget(
84
+ let target = blocksStorageTarget(
84
85
  parsePropertyOptions(definition.optionsJson),
85
86
  );
86
87
  await db.transaction(async (tx) => {
87
88
  await lockDatabaseMemberships(tx, [membership.id]);
89
+ const [lockedDefinition] = await tx
90
+ .select()
91
+ .from(schema.documentPropertyDefinitions)
92
+ .where(eq(schema.documentPropertyDefinitions.id, propertyId));
93
+ const [lockedMembership] = await tx
94
+ .select({ id: schema.contentDatabaseItems.id })
95
+ .from(schema.contentDatabaseItems)
96
+ .where(
97
+ and(
98
+ eq(schema.contentDatabaseItems.id, membership.id),
99
+ eq(schema.contentDatabaseItems.databaseId, database.id),
100
+ eq(schema.contentDatabaseItems.documentId, documentId),
101
+ ),
102
+ );
103
+ if (!lockedDefinition || lockedDefinition.databaseId !== database.id) {
104
+ throw new Error(`Property "${propertyId}" not found`);
105
+ }
106
+ if (!lockedMembership) {
107
+ throw new Error("Document is not part of this database.");
108
+ }
109
+ if (
110
+ !isBlocksPropertyType(lockedDefinition.type as DocumentPropertyType)
111
+ ) {
112
+ throw new Error(
113
+ "Property type changed before the operation completed.",
114
+ );
115
+ }
116
+ target = blocksStorageTarget(
117
+ parsePropertyOptions(lockedDefinition.optionsJson),
118
+ );
88
119
  if (target === "document_body") {
89
120
  await tx
90
121
  .update(schema.documents)
@@ -130,9 +161,13 @@ export default defineAction({
130
161
 
131
162
  const valueJson = normalizedValueJson(type, value);
132
163
  await db.transaction(async (tx) => {
164
+ await lockContentDatabaseMutation(
165
+ tx as unknown as ReturnType<typeof getDb>,
166
+ database.id,
167
+ );
133
168
  const [lockedDatabase] = await tx
134
- .update(schema.contentDatabases)
135
- .set({ updatedAt: sql`${schema.contentDatabases.updatedAt}` })
169
+ .select({ id: schema.contentDatabases.id })
170
+ .from(schema.contentDatabases)
136
171
  .where(
137
172
  and(
138
173
  eq(schema.contentDatabases.id, database.id),
@@ -140,38 +175,43 @@ export default defineAction({
140
175
  eq(schema.contentDatabases.ownerEmail, database.ownerEmail),
141
176
  isNull(schema.contentDatabases.deletedAt),
142
177
  ),
143
- )
144
- .returning({ id: schema.contentDatabases.id });
178
+ );
145
179
  if (!lockedDatabase) throw new Error("Database is no longer active.");
180
+ await lockDatabaseMemberships(tx, [membership.id]);
146
181
  const [lockedDefinition] = await tx
147
- .update(schema.documentPropertyDefinitions)
148
- .set({
149
- updatedAt: sql`${schema.documentPropertyDefinitions.updatedAt}`,
150
- })
182
+ .select()
183
+ .from(schema.documentPropertyDefinitions)
184
+ .where(eq(schema.documentPropertyDefinitions.id, propertyId));
185
+ const [lockedMembership] = await tx
186
+ .select({ id: schema.contentDatabaseItems.id })
187
+ .from(schema.contentDatabaseItems)
151
188
  .where(
152
189
  and(
153
- eq(schema.documentPropertyDefinitions.id, propertyId),
154
- eq(schema.documentPropertyDefinitions.databaseId, database.id),
155
- eq(
156
- schema.documentPropertyDefinitions.ownerEmail,
157
- database.ownerEmail,
158
- ),
190
+ eq(schema.contentDatabaseItems.id, membership.id),
191
+ eq(schema.contentDatabaseItems.databaseId, database.id),
192
+ eq(schema.contentDatabaseItems.documentId, documentId),
159
193
  ),
160
- )
161
- .returning({
162
- type: schema.documentPropertyDefinitions.type,
163
- systemRole: schema.documentPropertyDefinitions.systemRole,
164
- });
165
- if (
166
- !lockedDefinition ||
167
- lockedDefinition.type !== definition.type ||
168
- lockedDefinition.systemRole
169
- ) {
194
+ );
195
+ if (!lockedDefinition || lockedDefinition.databaseId !== database.id) {
196
+ throw new Error(`Property "${propertyId}" not found`);
197
+ }
198
+ if (!lockedMembership) {
199
+ throw new Error("Document is not part of this database.");
200
+ }
201
+ const lockedType = lockedDefinition.type as DocumentPropertyType;
202
+ if (lockedType !== type) {
170
203
  throw new Error(
171
- `Property "${propertyId}" changed or was deleted before its value could be written.`,
204
+ "Property type changed before the operation completed.",
172
205
  );
173
206
  }
174
- await lockDatabaseMemberships(tx, [membership.id]);
207
+ if (isBlocksPropertyType(lockedType)) {
208
+ throw new Error(
209
+ "Property type changed before the operation completed.",
210
+ );
211
+ }
212
+ if (isComputedPropertyType(lockedType)) {
213
+ throw new Error("Computed properties cannot be edited.");
214
+ }
175
215
  const [conflictingClaim] = await tx
176
216
  .select({ id: schema.contentDatabaseItemKeyClaims.id })
177
217
  .from(schema.contentDatabaseItemKeyClaims)
@@ -25,6 +25,10 @@ import {
25
25
  type DocumentPropertyType,
26
26
  type DocumentPropertyValue,
27
27
  } from "../shared/properties.js";
28
+ import {
29
+ lockContentDatabaseMutation,
30
+ touchContentDatabase,
31
+ } from "./_content-database-mutation-lock.js";
28
32
  import { ensureDocumentFilesMembership } from "./_content-files.js";
29
33
  import { nanoid, parseDatabaseViewConfig } from "./_property-utils.js";
30
34
 
@@ -47,6 +51,21 @@ const submitContentDatabaseFormSchema = z.object({
47
51
  type PropertyDefinitionRow =
48
52
  typeof schema.documentPropertyDefinitions.$inferSelect;
49
53
 
54
+ function propertyDefinitionFingerprint(definitions: PropertyDefinitionRow[]) {
55
+ return JSON.stringify(
56
+ definitions
57
+ .map((definition) => ({
58
+ id: definition.id,
59
+ name: definition.name,
60
+ type: definition.type,
61
+ systemRole: definition.systemRole,
62
+ visibility: definition.visibility,
63
+ optionsJson: definition.optionsJson,
64
+ }))
65
+ .sort((left, right) => left.id.localeCompare(right.id)),
66
+ );
67
+ }
68
+
50
69
  function resolveFormView(
51
70
  views: ContentDatabaseView[],
52
71
  activeViewId: string,
@@ -231,6 +250,7 @@ export default defineAction({
231
250
  ),
232
251
  ),
233
252
  );
253
+ const definitionsFingerprint = propertyDefinitionFingerprint(definitions);
234
254
  const viewConfig = parseDatabaseViewConfig(database.viewConfigJson);
235
255
  const formView = resolveFormView(
236
256
  viewConfig.views,
@@ -310,6 +330,35 @@ export default defineAction({
310
330
  const createdBy = getRequestUserEmail() ?? database.ownerEmail;
311
331
 
312
332
  await db.transaction(async (tx) => {
333
+ await lockContentDatabaseMutation(
334
+ tx as unknown as ReturnType<typeof getDb>,
335
+ databaseId,
336
+ );
337
+ await touchContentDatabase(
338
+ tx as unknown as ReturnType<typeof getDb>,
339
+ databaseId,
340
+ now,
341
+ );
342
+ const lockedDefinitions = await tx
343
+ .select()
344
+ .from(schema.documentPropertyDefinitions)
345
+ .where(
346
+ and(
347
+ eq(schema.documentPropertyDefinitions.databaseId, databaseId),
348
+ eq(
349
+ schema.documentPropertyDefinitions.ownerEmail,
350
+ database.ownerEmail,
351
+ ),
352
+ ),
353
+ );
354
+ if (
355
+ propertyDefinitionFingerprint(lockedDefinitions) !==
356
+ definitionsFingerprint
357
+ ) {
358
+ throw new Error(
359
+ "Database properties changed before form submission completed.",
360
+ );
361
+ }
313
362
  const [maxDocumentPosition] = await tx
314
363
  .select({ max: sql<number>`COALESCE(MAX(position), -1)` })
315
364
  .from(schema.documents)
@@ -356,7 +356,7 @@ async function transcribeMedia(media: AudioOnlyTranscriptionMedia) {
356
356
  );
357
357
  }
358
358
  throw new Error(
359
- `No media transcription provider is available. Connect Builder.io in Settings -> File uploads or configure GROQ_API_KEY. ${groqError}`,
359
+ `No media transcription provider is available. Connect Builder.io (free tier available) in Settings -> File uploads or configure GROQ_API_KEY. ${groqError}`,
360
360
  );
361
361
  }
362
362
  }
@@ -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
+ }
@@ -129,7 +129,7 @@ async function uploadMediaFile(
129
129
  const serverMessage = uploadResponseMessage(response, body, kind);
130
130
  if (isBuilderReconnectError(serverMessage)) {
131
131
  throw new Error(
132
- "Builder.io is connected, but the saved connection was rejected. Reconnect Builder.io in Settings -> File uploads, then try again.",
132
+ "Builder.io is connected, but the saved connection was rejected. Reconnect Builder.io in Settings -> File uploads (free tier available), then try again.",
133
133
  );
134
134
  }
135
135
  if (
@@ -139,7 +139,7 @@ async function uploadMediaFile(
139
139
  )
140
140
  ) {
141
141
  throw new Error(
142
- `${mediaUploadLabel(kind)} uploads need file storage. Connect Builder.io in Settings -> File uploads, then try again.`,
142
+ `${mediaUploadLabel(kind)} uploads need file storage. Connect Builder.io in Settings -> File uploads (free tier available), then try again.`,
143
143
  );
144
144
  }
145
145
  throw new Error(serverMessage);
@@ -227,7 +227,7 @@ const databaseMessages = {
227
227
  collapseAllGroups: "Collapse all groups",
228
228
  color: "Color",
229
229
  connectYourBuilderAccountToBrowseItsSpaces:
230
- "Connect your Builder account to browse its spaces and models.",
230
+ "Connect your Builder account (free tier available) to browse its spaces and models.",
231
231
  connectedSources: "Connected sources",
232
232
  couldntSyncRetry: "Couldn’t sync · Retry",
233
233
  databasePagePreview: "Database page preview",
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: added
3
+ date: 2026-08-01
4
+ ---
5
+
6
+ Content can reorganize every row in an existing database as one verified, reversible operation.
@@ -9,7 +9,7 @@ This generated matrix tracks whether high-value Content UI operations use the sa
9
9
  | database.lifecycle-and-trash | database | Create, soft-delete, restore, list, and inspect content databases | action-backed | `create-content-database`, `create-inline-content-database`, `delete-content-database`, `get-content-database`, `list-content-databases`, `list-trashed-content-databases`, `restore-content-database` | `app/components/editor/SlashCommandMenu.tsx`, `app/hooks/use-content-database.ts`, `app/hooks/use-documents.ts` | Database pages and database records are created, read, soft-deleted, restored, and listed. | - | - | P0 | covered | `actions/content-database-lifecycle.db.test.ts` | `database-source-scope` | - |
10
10
  | database.private-preview-drafts | database | Persist and reconcile a user's private database-page preview draft | action-backed | `get-preview-document-draft`, `update-preview-document-draft` | `app/components/editor/database/DatabaseView.tsx`, `app/hooks/use-documents.ts` | A user's private preview draft is read, saved, conflict-checked, or deleted without changing the shared database page until the normal save flow applies it. | These per-user editor-state actions are intentionally hidden from agent tools because preview drafts are a private UI recovery mechanism. | - | P1 | covered | `actions/preview-document-draft.db.test.ts` | - | - |
11
11
  | database.properties-and-view-config | database | Configure properties, values, ordering, and saved views | action-backed | `configure-document-property`, `delete-document-property`, `duplicate-document-property`, `get-content-database-personal-view`, `list-document-properties`, `reorder-document-property`, `set-document-property`, `update-content-database-personal-view`, `update-content-database-view` | `app/components/editor/DocumentProperties.tsx`, `app/components/editor/DocumentDatabase.tsx`, `app/components/editor/database/DatabaseView.tsx`, `app/hooks/use-document-properties.ts` | Property schemas, property values, property order, filters, sorts, grouping, hidden columns, view type, and view settings are stored. | - | - | P0 | covered | `actions/bind-content-database-source-field.db.test.ts`, `actions/content-database-source-actions.test.ts`, `actions/resync-content-database-source.db.test.ts` | `database-source-scope` | - |
12
- | database.rows | database | Add, duplicate, move, open, edit, and remove database rows | action-backed | `add-database-item`, `upsert-database-item-by-key`, `remove-database-items`, `duplicate-database-items`, `duplicate-database-item`, `move-database-item`, `set-document-property` | `app/components/editor/DocumentDatabase.tsx`, `app/components/editor/database/DatabaseView.tsx` | Database row memberships and ordering are created, duplicated, moved, edited, and removed without deleting the backing page. | - | - | P0 | covered | `actions/database-row-batch-actions.db.test.ts`, `parity/__tests__/database-row-batch-reliability.test.ts` | `database-bulk-row-reliability` | - |
12
+ | database.rows | database | Add, duplicate, move, open, edit, and remove database rows | action-backed | `add-database-item`, `upsert-database-item-by-key`, `remove-database-items`, `duplicate-database-items`, `duplicate-database-item`, `migrate-content-database-rows`, `move-database-item`, `set-document-property` | `app/components/editor/DocumentDatabase.tsx`, `app/components/editor/database/DatabaseView.tsx` | Database row memberships and ordering are created, duplicated, moved, edited, and removed without deleting the backing page; bounded migrations atomically update row bodies and properties through the same canonical data model. | - | - | P0 | covered | `actions/database-row-batch-actions.db.test.ts`, `actions/migrate-content-database-rows.db.test.ts`, `parity/__tests__/database-row-batch-reliability.test.ts` | `database-bulk-row-reliability` | - |
13
13
  | database.table-query-page | database | Query one constrained page while retaining database metadata | action-backed | `query-content-database-items` | `app/components/editor/database/DatabaseView.tsx`, `app/hooks/use-content-database.ts` | - | This UI-only bounded projection is intentionally hidden with agentTool: false; agents use get-content-database for the complete database contract. | - | P0 | covered | `actions/content-database-lifecycle.db.test.ts`, `app/hooks/use-content-database.test.ts` | - | - |
14
14
  | editor.agent-assist-prompts | editor | Ask AI from slash generation or comment context | client-assist | - | `app/components/editor/SlashCommandMenu.tsx`, `app/components/editor/CommentsSidebar.tsx` | No direct durable mutation; the prompt asks the agent to use document actions when it decides to write. | - | - | P1 | none | - | - | - |
15
15
  | editor.client-formatting-and-insertions | editor | Rich text formatting, selection state, slash block insertion, and copy actions | client-only-ephemeral | - | `app/components/editor/BubbleToolbar.tsx`, `app/components/editor/SlashCommandMenu.tsx`, `app/components/editor/DocumentToolbar.tsx` | - | - | - | P1 | none | - | - | - |
@@ -317,9 +317,9 @@ export const parityMatrix: ParityRow[] = [
317
317
  "app/components/editor/database/DatabaseView.tsx",
318
318
  ],
319
319
  durableEffect:
320
- "Database row memberships and ordering are created, duplicated, moved, edited, and removed without deleting the backing page.",
320
+ "Database row memberships and ordering are created, duplicated, moved, edited, and removed without deleting the backing page; bounded migrations atomically update row bodies and properties through the same canonical data model.",
321
321
  uiImplementation:
322
- "Row controls call row actions; selected-row duplicate/removal call bounded batch actions, while bulk property edits remain a later reliability slice.",
322
+ "Row controls call row actions; selected-row duplicate/removal call bounded batch actions, while bounded whole-database schema-and-body migrations use one validated, receipt-backed action instead of many partial writes.",
323
323
  status: "action-backed",
324
324
  actions: [
325
325
  "add-database-item",
@@ -327,6 +327,7 @@ export const parityMatrix: ParityRow[] = [
327
327
  "remove-database-items",
328
328
  "duplicate-database-items",
329
329
  "duplicate-database-item",
330
+ "migrate-content-database-rows",
330
331
  "move-database-item",
331
332
  "set-document-property",
332
333
  ],
@@ -337,6 +338,7 @@ export const parityMatrix: ParityRow[] = [
337
338
  followUpPR: null,
338
339
  coverageRefs: [
339
340
  "actions/database-row-batch-actions.db.test.ts",
341
+ "actions/migrate-content-database-rows.db.test.ts",
340
342
  "parity/__tests__/database-row-batch-reliability.test.ts",
341
343
  ],
342
344
  evalScenarioIds: ["database-bulk-row-reliability"],
@@ -464,6 +464,36 @@ export const contentDatabaseSourceExecutionClaims = table(
464
464
  },
465
465
  );
466
466
 
467
+ export const contentDatabaseMigrationReceipts = table(
468
+ "content_database_migration_receipts",
469
+ {
470
+ id: text("id").primaryKey(),
471
+ ownerEmail: text("owner_email").notNull().default("local@localhost"),
472
+ orgId: text("org_id"),
473
+ databaseId: text("database_id").notNull(),
474
+ databaseDocumentId: text("database_document_id").notNull(),
475
+ idempotencyKey: text("idempotency_key").notNull(),
476
+ planHash: text("plan_hash").notNull(),
477
+ state: text("state").notNull(),
478
+ preDigest: text("pre_digest").notNull(),
479
+ postDigest: text("post_digest").notNull(),
480
+ rollbackJson: text("rollback_json").notNull().default("{}"),
481
+ resultJson: text("result_json").notNull().default("{}"),
482
+ createdAt: text("created_at").notNull().default(now()),
483
+ updatedAt: text("updated_at").notNull().default(now()),
484
+ },
485
+ (receipt) => [
486
+ uniqueIndex("content_database_migration_receipts_database_key_unique").on(
487
+ receipt.databaseId,
488
+ receipt.idempotencyKey,
489
+ ),
490
+ index("content_database_migration_receipts_owner_database_idx").on(
491
+ receipt.ownerEmail,
492
+ receipt.databaseId,
493
+ ),
494
+ ],
495
+ );
496
+
467
497
  export const documentPropertyValues = table("document_property_values", {
468
498
  id: text("id").primaryKey(),
469
499
  ownerEmail: text("owner_email").notNull().default("local@localhost"),
@@ -932,6 +932,30 @@ const runContentMigrations = runMigrations(
932
932
  name: "content-database-item-stable-key-single-active-claim",
933
933
  sql: `CREATE UNIQUE INDEX IF NOT EXISTS content_database_item_key_claims_database_property_document_unique ON content_database_item_key_claims (database_id, property_id, document_id)`,
934
934
  },
935
+ {
936
+ version: 80,
937
+ name: "content-database-migration-receipts",
938
+ sql: `CREATE TABLE IF NOT EXISTS content_database_migration_receipts (
939
+ id TEXT PRIMARY KEY,
940
+ owner_email TEXT NOT NULL DEFAULT 'local@localhost',
941
+ org_id TEXT,
942
+ database_id TEXT NOT NULL,
943
+ database_document_id TEXT NOT NULL,
944
+ idempotency_key TEXT NOT NULL,
945
+ plan_hash TEXT NOT NULL,
946
+ state TEXT NOT NULL,
947
+ pre_digest TEXT NOT NULL,
948
+ post_digest TEXT NOT NULL,
949
+ rollback_json TEXT NOT NULL DEFAULT '{}',
950
+ result_json TEXT NOT NULL DEFAULT '{}',
951
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
952
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
953
+ );
954
+ CREATE UNIQUE INDEX IF NOT EXISTS content_database_migration_receipts_database_key_unique
955
+ ON content_database_migration_receipts (database_id, idempotency_key);
956
+ CREATE INDEX IF NOT EXISTS content_database_migration_receipts_owner_database_idx
957
+ ON content_database_migration_receipts (owner_email, database_id)`,
958
+ },
935
959
  ],
936
960
  { table: "content_migrations" },
937
961
  );
@@ -24,14 +24,14 @@ export default async (nitroApp: any): Promise<void> => {
24
24
  required: false,
25
25
  title: "Media uploads",
26
26
  description:
27
- "Connect Builder.io to upload and embed images, videos, and audio files in Content documents.",
27
+ "Connect Builder.io (free tier available) to upload and embed images, videos, and audio files in Content documents.",
28
28
  methods: [
29
29
  {
30
30
  id: "builder",
31
31
  kind: "builder-cli-auth",
32
32
  label: "Connect Builder.io",
33
33
  description:
34
- "One-click file storage for media blocks. Free during beta.",
34
+ "One-click file storage for media blocks. Builder.io's free tier includes file storage.",
35
35
  primary: true,
36
36
  badge: "free",
37
37
  payload: { scope: "browser" },