@agent-native/core 0.123.0 → 0.123.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (334) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +24 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/cli/templates-meta.ts +12 -0
  5. package/corpus/core/src/deploy/build.ts +8 -0
  6. package/corpus/core/src/server/builder-browser.ts +76 -0
  7. package/corpus/core/src/server/core-routes-plugin.ts +15 -5
  8. package/corpus/templates/assets/app/global.css +0 -4
  9. package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +195 -167
  10. package/corpus/templates/assets/changelog/2026-07-23-drafts-preview-panel-now-fills-the-full-width-with-a-large-p.md +6 -0
  11. package/corpus/templates/content/actions/_builder-cms-source-adapter.ts +1 -0
  12. package/corpus/templates/content/actions/_builder-cms-write-client.ts +55 -9
  13. package/corpus/templates/content/actions/_database-source-utils.ts +756 -182
  14. package/corpus/templates/content/actions/change-content-database-source-role.ts +21 -20
  15. package/corpus/templates/content/actions/execute-builder-source-execution.ts +49 -8
  16. package/corpus/templates/content/actions/materialize-builder-required-fields.ts +42 -9
  17. package/corpus/templates/content/actions/prepare-builder-source-review.ts +88 -90
  18. package/corpus/templates/content/actions/preview-builder-source-review.ts +4 -3
  19. package/corpus/templates/content/actions/refresh-content-database-source.ts +36 -9
  20. package/corpus/templates/content/actions/set-content-database-source-write-mode.ts +28 -24
  21. package/corpus/templates/content/app/components/editor/BubbleToolbar.tsx +62 -12
  22. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +91 -16
  23. package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +15 -1
  24. package/corpus/templates/content/app/components/editor/SlashCommandMenu.tsx +234 -44
  25. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +194 -16
  26. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +95 -42
  27. package/corpus/templates/content/app/components/editor/database-sources/BuilderSourceReviewDialog.tsx +4 -2
  28. package/corpus/templates/content/app/components/editor/extensions/CodeBlockNode.tsx +10 -166
  29. package/corpus/templates/content/app/components/editor/extensions/VideoBlock.tsx +32 -8
  30. package/corpus/templates/content/app/components/editor/extensions/VideoNode.ts +14 -0
  31. package/corpus/templates/content/app/components/editor/registrySlashItems.ts +5 -1
  32. package/corpus/templates/content/app/hooks/use-content-database.ts +59 -2
  33. package/corpus/templates/content/app/hooks/use-documents.ts +18 -26
  34. package/corpus/templates/content/app/root.tsx +1 -6
  35. package/corpus/templates/content/changelog/2026-07-24-builder-can-now-publish-approved-updates-to-entries-that-are.md +6 -0
  36. package/corpus/templates/content/changelog/2026-07-24-builder-collection-loading-no-longer-restarts-from-the-begin.md +6 -0
  37. package/corpus/templates/content/changelog/2026-07-24-builder-connections-now-complete-securely-from-netlify-deplo.md +6 -0
  38. package/corpus/templates/content/changelog/2026-07-24-builder-draft-creation-now-scopes-execution-to-the-selected-.md +6 -0
  39. package/corpus/templates/content/changelog/2026-07-24-builder-review-now-distinguishes-preparing-a-safe-dry-run-from.md +6 -0
  40. package/corpus/templates/content/changelog/2026-07-24-builder-source-imports-now-recover-from-a-transient-paginati.md +6 -0
  41. package/corpus/templates/content/changelog/2026-07-24-builder-source-refresh-now-preserves-the-provider-bound-fiel.md +6 -0
  42. package/corpus/templates/content/changelog/2026-07-24-builder-update-reviews-now-open-reliably-on-large-collection.md +6 -0
  43. package/corpus/templates/content/changelog/2026-07-24-builder-write-policy-controls-now-reflect-successful-changes.md +6 -0
  44. package/corpus/templates/content/changelog/2026-07-24-date-properties-now-save-reliably-when-selected-with-the-nat.md +6 -0
  45. package/corpus/templates/content/changelog/2026-07-24-editor-slash-search-now-keeps-multi-word-block-names-open.md +6 -0
  46. package/corpus/templates/content/changelog/2026-07-24-exact-editor-slash-commands-now-execute-on-enter-even-if-the.md +6 -0
  47. package/corpus/templates/content/changelog/2026-07-24-new-collaborative-pages-now-save-their-first-edits.md +6 -0
  48. package/corpus/templates/content/changelog/2026-07-24-new-local-builder-rows-no-longer-remain-locked-behind-a-none.md +6 -0
  49. package/corpus/templates/content/changelog/2026-07-24-opening-or-closing-a-collaborative-document-no-longer-lets-u.md +6 -0
  50. package/corpus/templates/content/changelog/2026-07-24-selected-text-now-opens-the-link-editor-with-command-k-or-co.md +6 -0
  51. package/corpus/templates/content/changelog/2026-07-24-slash-menu-block-choices-no-longer-stall-pointer-interaction.md +6 -0
  52. package/corpus/templates/content/changelog/2026-07-24-uploaded-and-embedded-media-now-stay-intact-while-collaborative-document-drafts-save.md +6 -0
  53. package/corpus/templates/content/changelog/2026-07-24-video-link-insertion-now-keeps-its-source-panel-open-while-t.md +6 -0
  54. package/corpus/templates/content/changelog/2026-07-26-builder-publishing-now-shows-safe-validation-details-instead.md +6 -0
  55. package/corpus/templates/content/changelog/2026-07-26-builder-reviews-stay-responsive-on-large-collections-and-pre.md +6 -0
  56. package/corpus/templates/content/changelog/2026-07-26-collaborative-documents-no-longer-flash-duplicated-recent-bl.md +6 -0
  57. package/corpus/templates/content/changelog/2026-07-26-corrected-builder-updates-are-now-reviewed-separately-from-f.md +6 -0
  58. package/corpus/templates/content/changelog/2026-07-26-documents-now-remain-read-only-until-their-live-collaborativ.md +6 -0
  59. package/corpus/templates/content/changelog/2026-07-26-slash-command-menus-now-stay-reachable-when-editing-near-the.md +6 -0
  60. package/corpus/templates/content/changelog/2026-07-26-the-slash-menu-now-shows-one-clear-callout-choice-instead-of.md +6 -0
  61. package/corpus/templates/content/shared/api.ts +1 -0
  62. package/corpus/templates/content/shared/builder-mdx.ts +73 -16
  63. package/corpus/templates/crm/.agents/skills/agent-native-docs/SKILL.md +115 -0
  64. package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +177 -0
  65. package/corpus/templates/crm/.agents/skills/crm/SKILL.md +205 -0
  66. package/corpus/templates/crm/.agents/skills/customizing-agent-native/SKILL.md +220 -0
  67. package/corpus/templates/crm/.agents/skills/feature-flags/SKILL.md +169 -0
  68. package/corpus/templates/crm/.agents/skills/sharing/SKILL.md +228 -0
  69. package/corpus/templates/crm/.agents/skills/storing-data/SKILL.md +178 -0
  70. package/corpus/templates/crm/.agents/skills/upgrade-agent-native/SKILL.md +122 -0
  71. package/corpus/templates/crm/.env.example +5 -0
  72. package/corpus/templates/crm/AGENTS.md +82 -0
  73. package/corpus/templates/crm/CHANGELOG.md +25 -0
  74. package/corpus/templates/crm/DEVELOPING.md +66 -0
  75. package/corpus/templates/crm/README.md +122 -0
  76. package/corpus/templates/crm/_gitignore +12 -0
  77. package/corpus/templates/crm/actions/_crm-action-utils.ts +98 -0
  78. package/corpus/templates/crm/actions/_crm-attribute-utils.ts +219 -0
  79. package/corpus/templates/crm/actions/_crm-dashboard.ts +69 -0
  80. package/corpus/templates/crm/actions/_crm-data-program-actions.ts +15 -0
  81. package/corpus/templates/crm/actions/_crm-list-utils.ts +775 -0
  82. package/corpus/templates/crm/actions/_crm-signal-utils.ts +79 -0
  83. package/corpus/templates/crm/actions/add-crm-record-to-list.ts +164 -0
  84. package/corpus/templates/crm/actions/apply-crm-proposals.ts +291 -0
  85. package/corpus/templates/crm/actions/archive-crm-attribute.ts +69 -0
  86. package/corpus/templates/crm/actions/attach-call-evidence.ts +170 -0
  87. package/corpus/templates/crm/actions/configure-crm-connection.ts +126 -0
  88. package/corpus/templates/crm/actions/configure-native-crm.ts +44 -0
  89. package/corpus/templates/crm/actions/create-crm-attribute.ts +350 -0
  90. package/corpus/templates/crm/actions/create-crm-list.ts +194 -0
  91. package/corpus/templates/crm/actions/create-crm-record.ts +148 -0
  92. package/corpus/templates/crm/actions/create-crm-signal-tracker.ts +58 -0
  93. package/corpus/templates/crm/actions/delete-crm-saved-view.ts +68 -0
  94. package/corpus/templates/crm/actions/delete-staged-dataset.ts +14 -0
  95. package/corpus/templates/crm/actions/estimate-crm-enrichment.ts +229 -0
  96. package/corpus/templates/crm/actions/find-crm-duplicates.ts +87 -0
  97. package/corpus/templates/crm/actions/get-crm-automation-recipe.ts +36 -0
  98. package/corpus/templates/crm/actions/get-crm-dashboard-panel.ts +35 -0
  99. package/corpus/templates/crm/actions/get-crm-dashboard.ts +14 -0
  100. package/corpus/templates/crm/actions/get-crm-overview.ts +13 -0
  101. package/corpus/templates/crm/actions/get-crm-pipeline-data.ts +61 -0
  102. package/corpus/templates/crm/actions/get-crm-record-page.ts +287 -0
  103. package/corpus/templates/crm/actions/get-crm-record.ts +75 -0
  104. package/corpus/templates/crm/actions/get-crm-workspace.ts +364 -0
  105. package/corpus/templates/crm/actions/install-crm-pipeline-dashboard.ts +81 -0
  106. package/corpus/templates/crm/actions/list-crm-attributes.ts +71 -0
  107. package/corpus/templates/crm/actions/list-crm-connections.ts +68 -0
  108. package/corpus/templates/crm/actions/list-crm-dashboard-revisions.ts +15 -0
  109. package/corpus/templates/crm/actions/list-crm-dashboards.ts +15 -0
  110. package/corpus/templates/crm/actions/list-crm-enrichment-slots.ts +28 -0
  111. package/corpus/templates/crm/actions/list-crm-list-entries.ts +192 -0
  112. package/corpus/templates/crm/actions/list-crm-lists.ts +80 -0
  113. package/corpus/templates/crm/actions/list-crm-proposals.ts +55 -0
  114. package/corpus/templates/crm/actions/list-crm-record-field-history.ts +201 -0
  115. package/corpus/templates/crm/actions/list-crm-record-values.ts +200 -0
  116. package/corpus/templates/crm/actions/list-crm-records.ts +103 -0
  117. package/corpus/templates/crm/actions/list-crm-saved-views.ts +66 -0
  118. package/corpus/templates/crm/actions/list-crm-signal-hits.ts +43 -0
  119. package/corpus/templates/crm/actions/list-crm-signal-trackers.ts +32 -0
  120. package/corpus/templates/crm/actions/list-crm-tasks.ts +22 -0
  121. package/corpus/templates/crm/actions/list-staged-datasets.ts +14 -0
  122. package/corpus/templates/crm/actions/list-workspace-connections.ts +47 -0
  123. package/corpus/templates/crm/actions/manage-crm-attribute-option.ts +272 -0
  124. package/corpus/templates/crm/actions/manage-crm-signal-tracker.ts +87 -0
  125. package/corpus/templates/crm/actions/manage-crm-task.ts +132 -0
  126. package/corpus/templates/crm/actions/merge-crm-records.ts +691 -0
  127. package/corpus/templates/crm/actions/navigate.ts +54 -0
  128. package/corpus/templates/crm/actions/provider-api-catalog.ts +22 -0
  129. package/corpus/templates/crm/actions/provider-api-docs.ts +54 -0
  130. package/corpus/templates/crm/actions/provider-api-request.ts +92 -0
  131. package/corpus/templates/crm/actions/query-staged-dataset.ts +44 -0
  132. package/corpus/templates/crm/actions/record-crm-call-insight.ts +160 -0
  133. package/corpus/templates/crm/actions/record-crm-smart-signal.ts +150 -0
  134. package/corpus/templates/crm/actions/remove-crm-list-entry.ts +79 -0
  135. package/corpus/templates/crm/actions/restore-crm-dashboard-revision.ts +23 -0
  136. package/corpus/templates/crm/actions/review-crm-signal.ts +31 -0
  137. package/corpus/templates/crm/actions/run-crm-attribute-fill.ts +443 -0
  138. package/corpus/templates/crm/actions/run-crm-enrichment.ts +647 -0
  139. package/corpus/templates/crm/actions/run-crm-saved-view-program.ts +103 -0
  140. package/corpus/templates/crm/actions/run-crm-signal-trackers.ts +265 -0
  141. package/corpus/templates/crm/actions/run.ts +7 -0
  142. package/corpus/templates/crm/actions/save-crm-dashboard.ts +51 -0
  143. package/corpus/templates/crm/actions/save-crm-saved-view.ts +296 -0
  144. package/corpus/templates/crm/actions/sync-crm.ts +146 -0
  145. package/corpus/templates/crm/actions/update-crm-attribute.ts +111 -0
  146. package/corpus/templates/crm/actions/update-crm-list-entry.ts +102 -0
  147. package/corpus/templates/crm/actions/update-crm-list.ts +97 -0
  148. package/corpus/templates/crm/actions/update-crm-record.ts +543 -0
  149. package/corpus/templates/crm/actions/view-screen.ts +324 -0
  150. package/corpus/templates/crm/agent-native.app-skill.json +69 -0
  151. package/corpus/templates/crm/app/components/crm/CreateCrmRecordDialog.tsx +158 -0
  152. package/corpus/templates/crm/app/components/crm/CrmDashboardPanel.tsx +78 -0
  153. package/corpus/templates/crm/app/components/crm/CrmSignalsPanel.tsx +220 -0
  154. package/corpus/templates/crm/app/components/crm/IntelligenceSettings.tsx +414 -0
  155. package/corpus/templates/crm/app/components/crm/RecordActions.tsx +648 -0
  156. package/corpus/templates/crm/app/components/crm/RecordGrid.tsx +488 -0
  157. package/corpus/templates/crm/app/components/crm/RecordWorkspace.tsx +232 -0
  158. package/corpus/templates/crm/app/components/crm/SavedViewDataProgram.tsx +93 -0
  159. package/corpus/templates/crm/app/components/crm/Surface.tsx +97 -0
  160. package/corpus/templates/crm/app/components/crm/WorkOverview.tsx +180 -0
  161. package/corpus/templates/crm/app/components/crm/board/CrmBoard.tsx +988 -0
  162. package/corpus/templates/crm/app/components/crm/board/board-model.ts +399 -0
  163. package/corpus/templates/crm/app/components/crm/board/entry-filter.ts +150 -0
  164. package/corpus/templates/crm/app/components/crm/board/view-draft.ts +227 -0
  165. package/corpus/templates/crm/app/components/crm/grid/CrmGrid.tsx +1033 -0
  166. package/corpus/templates/crm/app/components/crm/grid/GridCell.tsx +620 -0
  167. package/corpus/templates/crm/app/components/crm/grid/clipboard.ts +84 -0
  168. package/corpus/templates/crm/app/components/crm/grid/model.ts +304 -0
  169. package/corpus/templates/crm/app/components/crm/grid/navigation.ts +220 -0
  170. package/corpus/templates/crm/app/components/crm/grid/query.ts +214 -0
  171. package/corpus/templates/crm/app/components/crm/record/AttributePanel.tsx +192 -0
  172. package/corpus/templates/crm/app/components/crm/record/FieldHistory.tsx +179 -0
  173. package/corpus/templates/crm/app/components/crm/record/RecordHeader.tsx +103 -0
  174. package/corpus/templates/crm/app/components/crm/record/RecordLists.tsx +235 -0
  175. package/corpus/templates/crm/app/components/crm/record/RecordTabs.tsx +206 -0
  176. package/corpus/templates/crm/app/components/crm/record/field-editors.tsx +245 -0
  177. package/corpus/templates/crm/app/components/crm/record/record-data.ts +603 -0
  178. package/corpus/templates/crm/app/components/crm/settings/AdvancedSettings.tsx +49 -0
  179. package/corpus/templates/crm/app/components/crm/settings/AttributeOptionsEditor.tsx +441 -0
  180. package/corpus/templates/crm/app/components/crm/settings/ConnectionSettings.tsx +169 -0
  181. package/corpus/templates/crm/app/components/crm/settings/FieldsSettings.tsx +935 -0
  182. package/corpus/templates/crm/app/components/crm/settings/ListsSettings.tsx +339 -0
  183. package/corpus/templates/crm/app/components/crm/settings/settings-admin.ts +377 -0
  184. package/corpus/templates/crm/app/components/crm/shared/AttributeValueParts.tsx +69 -0
  185. package/corpus/templates/crm/app/components/crm/shared/attribute-value.ts +591 -0
  186. package/corpus/templates/crm/app/components/layout/CrmCommandMenu.tsx +556 -0
  187. package/corpus/templates/crm/app/components/layout/CrmLayout.tsx +130 -0
  188. package/corpus/templates/crm/app/components/layout/CrmSidebar.tsx +407 -0
  189. package/corpus/templates/crm/app/components/layout/command-palette-search.ts +126 -0
  190. package/corpus/templates/crm/app/components/layout/crm-ui-intents.ts +41 -0
  191. package/corpus/templates/crm/app/components/layout/sidebar-collapse.ts +40 -0
  192. package/corpus/templates/crm/app/components/layout/sidebar-lists.ts +109 -0
  193. package/corpus/templates/crm/app/components/ui/alert-dialog.tsx +1 -0
  194. package/corpus/templates/crm/app/components/ui/badge.tsx +1 -0
  195. package/corpus/templates/crm/app/components/ui/button.tsx +1 -0
  196. package/corpus/templates/crm/app/components/ui/card.tsx +1 -0
  197. package/corpus/templates/crm/app/components/ui/checkbox.tsx +1 -0
  198. package/corpus/templates/crm/app/components/ui/dialog.tsx +1 -0
  199. package/corpus/templates/crm/app/components/ui/dropdown-menu.tsx +1 -0
  200. package/corpus/templates/crm/app/components/ui/hover-card.tsx +1 -0
  201. package/corpus/templates/crm/app/components/ui/input.tsx +1 -0
  202. package/corpus/templates/crm/app/components/ui/label.tsx +1 -0
  203. package/corpus/templates/crm/app/components/ui/popover.tsx +1 -0
  204. package/corpus/templates/crm/app/components/ui/select.tsx +1 -0
  205. package/corpus/templates/crm/app/components/ui/sheet.tsx +1 -0
  206. package/corpus/templates/crm/app/components/ui/skeleton.tsx +1 -0
  207. package/corpus/templates/crm/app/components/ui/switch.tsx +1 -0
  208. package/corpus/templates/crm/app/components/ui/table.tsx +1 -0
  209. package/corpus/templates/crm/app/components/ui/tabs.tsx +1 -0
  210. package/corpus/templates/crm/app/components/ui/textarea.tsx +1 -0
  211. package/corpus/templates/crm/app/components/ui/toolkit-provider.tsx +17 -0
  212. package/corpus/templates/crm/app/components/ui/tooltip.tsx +1 -0
  213. package/corpus/templates/crm/app/design-system.ts +3 -0
  214. package/corpus/templates/crm/app/entry.client.tsx +19 -0
  215. package/corpus/templates/crm/app/entry.server.tsx +10 -0
  216. package/corpus/templates/crm/app/global.css +167 -0
  217. package/corpus/templates/crm/app/hooks/use-keyboard-shortcuts.ts +206 -0
  218. package/corpus/templates/crm/app/hooks/use-navigation-state.ts +48 -0
  219. package/corpus/templates/crm/app/i18n/en-US.ts +684 -0
  220. package/corpus/templates/crm/app/i18n/index.ts +34 -0
  221. package/corpus/templates/crm/app/lib/dashboard.ts +13 -0
  222. package/corpus/templates/crm/app/lib/navigation.ts +17 -0
  223. package/corpus/templates/crm/app/lib/tab-id.ts +1 -0
  224. package/corpus/templates/crm/app/lib/types.ts +172 -0
  225. package/corpus/templates/crm/app/lib/utils.ts +1 -0
  226. package/corpus/templates/crm/app/root.tsx +93 -0
  227. package/corpus/templates/crm/app/routes/_index.tsx +26 -0
  228. package/corpus/templates/crm/app/routes/accounts.tsx +41 -0
  229. package/corpus/templates/crm/app/routes/agent.tsx +5 -0
  230. package/corpus/templates/crm/app/routes/ask.tsx +53 -0
  231. package/corpus/templates/crm/app/routes/dashboard.tsx +118 -0
  232. package/corpus/templates/crm/app/routes/lists.tsx +228 -0
  233. package/corpus/templates/crm/app/routes/opportunities.tsx +41 -0
  234. package/corpus/templates/crm/app/routes/people.tsx +41 -0
  235. package/corpus/templates/crm/app/routes/proposals.tsx +388 -0
  236. package/corpus/templates/crm/app/routes/records.$recordId.tsx +53 -0
  237. package/corpus/templates/crm/app/routes/records.tsx +64 -0
  238. package/corpus/templates/crm/app/routes/settings.tsx +118 -0
  239. package/corpus/templates/crm/app/routes/setup.tsx +308 -0
  240. package/corpus/templates/crm/app/routes/tasks.tsx +252 -0
  241. package/corpus/templates/crm/app/routes/views.tsx +683 -0
  242. package/corpus/templates/crm/app/routes.ts +19 -0
  243. package/corpus/templates/crm/app/vite-env.d.ts +6 -0
  244. package/corpus/templates/crm/changelog/2026-07-26-any-list-or-view-can-be-shown-as-a-board-grouped-by-stage-so.md +6 -0
  245. package/corpus/templates/crm/changelog/2026-07-26-crm-now-finds-likely-duplicate-records-and-tells-you-exactly.md +6 -0
  246. package/corpus/templates/crm/changelog/2026-07-26-enrichment-now-shows-what-a-run-will-cost-before-it-starts-g.md +6 -0
  247. package/corpus/templates/crm/changelog/2026-07-26-lists-turn-any-set-of-records-into-a-pipeline-with-its-own-s.md +6 -0
  248. package/corpus/templates/crm/changelog/2026-07-26-moving-a-record-or-list-entry-into-a-stage-that-was-retired-.md +6 -0
  249. package/corpus/templates/crm/changelog/2026-07-26-opening-a-record-now-shows-one-page-with-its-fields-the-list.md +6 -0
  250. package/corpus/templates/crm/changelog/2026-07-26-press-cmd-k-to-jump-to-any-record-list-view-or-setting-and-u.md +6 -0
  251. package/corpus/templates/crm/changelog/2026-07-26-provider-record-edits-now-show-an-exact-before-after-diff-an.md +6 -0
  252. package/corpus/templates/crm/changelog/2026-07-26-record-page-attribute-labels-now-read-in-full-instead-of-bei.md +6 -0
  253. package/corpus/templates/crm/changelog/2026-07-26-records-now-use-typed-fields-currency-dates-ratings-status-s.md +6 -0
  254. package/corpus/templates/crm/changelog/2026-07-26-retyping-a-value-on-the-record-page-now-replaces-it-instead-.md +6 -0
  255. package/corpus/templates/crm/changelog/2026-07-26-settings-now-has-fields-and-lists-tabs-for-adding-fields-edi.md +6 -0
  256. package/corpus/templates/crm/changelog/2026-07-26-the-proposal-review-now-shows-the-field-that-actually-change.md +6 -0
  257. package/corpus/templates/crm/changelog/2026-07-26-the-record-grid-is-now-a-real-spreadsheet-filter-sort-and-pa.md +6 -0
  258. package/corpus/templates/crm/components.json +20 -0
  259. package/corpus/templates/crm/docs/architecture/crm-contract.md +214 -0
  260. package/corpus/templates/crm/docs/features/README.md +55 -0
  261. package/corpus/templates/crm/docs/features/f1-records-and-fields.mdx +52 -0
  262. package/corpus/templates/crm/docs/features/f2-lists-pipelines-and-views.mdx +48 -0
  263. package/corpus/templates/crm/docs/features/f3-work-and-record-quality.mdx +40 -0
  264. package/corpus/templates/crm/docs/features/f4-evidence-and-chat.mdx +47 -0
  265. package/corpus/templates/crm/learnings.defaults.md +5 -0
  266. package/corpus/templates/crm/netlify.toml +11 -0
  267. package/corpus/templates/crm/package.json +61 -0
  268. package/corpus/templates/crm/public/favicon.svg +1 -0
  269. package/corpus/templates/crm/public/icon-180.svg +1 -0
  270. package/corpus/templates/crm/public/manifest.json +11 -0
  271. package/corpus/templates/crm/react-router.config.ts +7 -0
  272. package/corpus/templates/crm/server/crm/adapter.ts +32 -0
  273. package/corpus/templates/crm/server/crm/crm-field-firewall.ts +64 -0
  274. package/corpus/templates/crm/server/crm/crm-mirror.ts +721 -0
  275. package/corpus/templates/crm/server/crm/field-policy-attributes.ts +48 -0
  276. package/corpus/templates/crm/server/crm/hubspot-adapter.ts +1146 -0
  277. package/corpus/templates/crm/server/crm/native-adapter.ts +1810 -0
  278. package/corpus/templates/crm/server/crm/provider-record-link.ts +264 -0
  279. package/corpus/templates/crm/server/crm/read-through.ts +207 -0
  280. package/corpus/templates/crm/server/crm/salesforce-adapter.ts +1255 -0
  281. package/corpus/templates/crm/server/db/crm-store.ts +1112 -0
  282. package/corpus/templates/crm/server/db/index.ts +191 -0
  283. package/corpus/templates/crm/server/db/schema.ts +647 -0
  284. package/corpus/templates/crm/server/lib/crm-query.ts +1558 -0
  285. package/corpus/templates/crm/server/lib/dedupe.ts +714 -0
  286. package/corpus/templates/crm/server/lib/enrichment-cost.ts +381 -0
  287. package/corpus/templates/crm/server/lib/enrichment-slots.ts +519 -0
  288. package/corpus/templates/crm/server/lib/intelligence/default-detectors.ts +65 -0
  289. package/corpus/templates/crm/server/lib/intelligence/evidence.ts +105 -0
  290. package/corpus/templates/crm/server/lib/intelligence/keyword-detector.ts +94 -0
  291. package/corpus/templates/crm/server/lib/intelligence/smart-detector.ts +39 -0
  292. package/corpus/templates/crm/server/lib/intelligence/summary.ts +19 -0
  293. package/corpus/templates/crm/server/lib/lifecycle.ts +634 -0
  294. package/corpus/templates/crm/server/lib/provider-api.ts +64 -0
  295. package/corpus/templates/crm/server/middleware/auth.ts +4 -0
  296. package/corpus/templates/crm/server/plugins/agent-chat.ts +65 -0
  297. package/corpus/templates/crm/server/plugins/auth.ts +14 -0
  298. package/corpus/templates/crm/server/plugins/core-routes.ts +17 -0
  299. package/corpus/templates/crm/server/plugins/db.ts +738 -0
  300. package/corpus/templates/crm/server/routes/[...page].get.ts +5 -0
  301. package/corpus/templates/crm/shared/crm-attributes.ts +469 -0
  302. package/corpus/templates/crm/shared/crm-automation-recipes.ts +132 -0
  303. package/corpus/templates/crm/shared/crm-contract.ts +417 -0
  304. package/corpus/templates/crm/shared/crm-navigation.ts +190 -0
  305. package/corpus/templates/crm/shared/crm-sales-config.ts +63 -0
  306. package/corpus/templates/crm/ssr-entry.ts +11 -0
  307. package/corpus/templates/crm/tsconfig.json +24 -0
  308. package/corpus/templates/crm/vite.config.ts +15 -0
  309. package/corpus/templates/crm/vitest.config.ts +5 -0
  310. package/corpus/templates/design/app/i18n-data.ts +12 -12
  311. package/corpus/templates/design/changelog/2026-07-26-apply-design-updates-from-a-centered-top-toolbar-without-cov.md +6 -0
  312. package/corpus/toolkit/CHANGELOG.md +6 -0
  313. package/corpus/toolkit/package.json +1 -1
  314. package/corpus/toolkit/src/editor/useCollabReconcile.ts +14 -1
  315. package/dist/cli/templates-meta.d.ts.map +1 -1
  316. package/dist/cli/templates-meta.js +12 -0
  317. package/dist/cli/templates-meta.js.map +1 -1
  318. package/dist/collab/routes.d.ts +2 -2
  319. package/dist/deploy/build.js +6 -0
  320. package/dist/deploy/build.js.map +1 -1
  321. package/dist/observability/routes.d.ts +3 -3
  322. package/dist/server/builder-browser.d.ts +13 -0
  323. package/dist/server/builder-browser.d.ts.map +1 -1
  324. package/dist/server/builder-browser.js +59 -0
  325. package/dist/server/builder-browser.js.map +1 -1
  326. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  327. package/dist/server/core-routes-plugin.js +10 -5
  328. package/dist/server/core-routes-plugin.js.map +1 -1
  329. package/dist/server/transcribe-voice.d.ts +1 -1
  330. package/package.json +2 -2
  331. package/src/cli/templates-meta.ts +12 -0
  332. package/src/deploy/build.ts +8 -0
  333. package/src/server/builder-browser.ts +76 -0
  334. package/src/server/core-routes-plugin.ts +15 -5
@@ -1,175 +1,19 @@
1
- import { useT } from "@agent-native/core/client/i18n";
2
- import { IconChevronDown, IconCheck } from "@tabler/icons-react";
3
1
  import { CodeBlockLowlight } from "@tiptap/extension-code-block-lowlight";
4
- import {
5
- NodeViewContent,
6
- NodeViewWrapper,
7
- ReactNodeViewRenderer,
8
- type NodeViewProps,
9
- } from "@tiptap/react";
10
2
  import { common, createLowlight } from "lowlight";
11
- import { useState, useRef, useEffect, useCallback } from "react";
12
-
13
- import { cn } from "@/lib/utils";
14
3
 
15
4
  const lowlight = createLowlight(common);
16
5
 
17
- const LANGUAGES = [
18
- { value: null, labelKey: "editor.plainText" },
19
- // i18n-ignore Stable programming-language names shown as their canonical names.
20
- { value: "javascript", label: "JavaScript" },
21
- { value: "typescript", label: "TypeScript" },
22
- { value: "python", label: "Python" },
23
- { value: "bash", label: "Bash" },
24
- { value: "shell", label: "Shell" },
25
- { value: "html", label: "HTML" },
26
- { value: "css", label: "CSS" },
27
- { value: "json", label: "JSON" },
28
- { value: "yaml", label: "YAML" },
29
- { value: "markdown", label: "Markdown" },
30
- { value: "sql", label: "SQL" },
31
- { value: "java", label: "Java" },
32
- { value: "c", label: "C" },
33
- { value: "cpp", label: "C++" },
34
- { value: "csharp", label: "C#" },
35
- { value: "go", label: "Go" },
36
- { value: "rust", label: "Rust" },
37
- { value: "ruby", label: "Ruby" },
38
- { value: "php", label: "PHP" },
39
- { value: "swift", label: "Swift" },
40
- { value: "kotlin", label: "Kotlin" },
41
- { value: "scala", label: "Scala" },
42
- { value: "r", label: "R" },
43
- { value: "perl", label: "Perl" },
44
- { value: "lua", label: "Lua" },
45
- { value: "xml", label: "XML" },
46
- { value: "graphql", label: "GraphQL" },
47
- { value: "dockerfile", label: "Dockerfile" },
48
- { value: "ini", label: "INI" },
49
- { value: "diff", label: "Diff" },
50
- ] as const;
51
-
52
- function languageLabel(
53
- language: (typeof LANGUAGES)[number],
54
- t: ReturnType<typeof useT>,
55
- ) {
56
- return "labelKey" in language ? t(language.labelKey) : language.label;
57
- }
58
-
59
- function CodeBlockView({ node, updateAttributes, editor }: NodeViewProps) {
60
- const t = useT();
61
- const [showPicker, setShowPicker] = useState(false);
62
- const [filter, setFilter] = useState("");
63
- const pickerRef = useRef<HTMLDivElement>(null);
64
- const filterRef = useRef<HTMLInputElement>(null);
65
- const isEditable = editor.isEditable;
66
-
67
- const currentLang = node.attrs.language as string | null;
68
- const currentLanguage = LANGUAGES.find(
69
- (l) =>
70
- l.value === currentLang ||
71
- (l.value === null && !currentLang) ||
72
- ((l.value as string) === "plaintext" && !currentLang),
73
- );
74
- const displayLabel =
75
- (currentLanguage ? languageLabel(currentLanguage, t) : currentLang) ??
76
- t("editor.plainText");
77
-
78
- const filteredLanguages = LANGUAGES.filter((l) =>
79
- languageLabel(l, t).toLowerCase().includes(filter.toLowerCase()),
80
- );
81
-
82
- const closePicker = useCallback(() => {
83
- setShowPicker(false);
84
- setFilter("");
85
- }, []);
86
-
87
- useEffect(() => {
88
- if (!showPicker) return;
89
- filterRef.current?.focus();
90
- const handleClick = (e: MouseEvent) => {
91
- if (pickerRef.current && !pickerRef.current.contains(e.target as Node)) {
92
- closePicker();
93
- }
94
- };
95
- document.addEventListener("mousedown", handleClick);
96
- return () => document.removeEventListener("mousedown", handleClick);
97
- }, [showPicker, closePicker]);
98
-
99
- return (
100
- <NodeViewWrapper className="notion-code-block-wrapper">
101
- <div className="notion-code-block-header" contentEditable={false}>
102
- <div className="relative" ref={pickerRef}>
103
- {isEditable ? (
104
- <button
105
- type="button"
106
- className="notion-code-lang-btn"
107
- onClick={() => setShowPicker(!showPicker)}
108
- >
109
- {displayLabel}
110
- <IconChevronDown size={12} />
111
- </button>
112
- ) : (
113
- <span className="notion-code-lang-btn notion-code-lang-btn--readonly">
114
- {displayLabel}
115
- </span>
116
- )}
117
- {showPicker && isEditable && (
118
- <div className="notion-code-lang-picker">
119
- <input
120
- ref={filterRef}
121
- type="text"
122
- value={filter}
123
- onChange={(e) => setFilter(e.target.value)}
124
- onKeyDown={(e) => {
125
- if (e.key === "Escape") closePicker();
126
- if (e.key === "Enter" && filteredLanguages.length > 0) {
127
- updateAttributes({
128
- language: filteredLanguages[0].value || "",
129
- });
130
- closePicker();
131
- }
132
- }}
133
- placeholder={t("editor.searchLanguages")}
134
- className="notion-code-lang-search"
135
- />
136
- <div className="notion-code-lang-list">
137
- {filteredLanguages.map((lang) => (
138
- <button
139
- key={lang.value ?? "plain"}
140
- type="button"
141
- className={cn(
142
- "notion-code-lang-option",
143
- (currentLang === lang.value ||
144
- (!currentLang && !lang.value)) &&
145
- "active",
146
- )}
147
- onClick={() => {
148
- updateAttributes({ language: lang.value || "" });
149
- closePicker();
150
- }}
151
- >
152
- {languageLabel(lang, t)}
153
- {(currentLang === lang.value ||
154
- (!currentLang && !lang.value)) && <IconCheck size={14} />}
155
- </button>
156
- ))}
157
- </div>
158
- </div>
159
- )}
160
- </div>
161
- </div>
162
- <pre>
163
- <NodeViewContent as={"code" as any} />
164
- </pre>
165
- </NodeViewWrapper>
166
- );
167
- }
168
-
6
+ /**
7
+ * Content's fenced code block.
8
+ *
9
+ * Keep the node on Tiptap's native DOM renderer. Mounting the former React
10
+ * node view could synchronously lock a collaborative editor as soon as a code
11
+ * block entered the document. The native renderer preserves the same
12
+ * `codeBlock` schema, language attribute, lowlight decorations, markdown
13
+ * round-trip, and keyboard behavior without a second React render tree inside
14
+ * ProseMirror.
15
+ */
169
16
  export const CodeBlock = CodeBlockLowlight.extend({
170
- addNodeView() {
171
- return ReactNodeViewRenderer(CodeBlockView);
172
- },
173
17
  addKeyboardShortcuts() {
174
18
  return {
175
19
  ...this.parent?.(),
@@ -151,9 +151,7 @@ export function VideoBlock({
151
151
  }: NodeViewProps) {
152
152
  const t = useT();
153
153
  const [isHovered, setIsHovered] = useState(false);
154
- const [sourcePanelOpen, setSourcePanelOpen] = useState(false);
155
154
  const [sourcePanelDismissed, setSourcePanelDismissed] = useState(false);
156
- const [sourceTab, setSourceTab] = useState<VideoSourceTab>("upload");
157
155
  const [videoUrl, setVideoUrl] = useState("");
158
156
  const [dragWidth, setDragWidth] = useState<number | null>(null);
159
157
  const [lightboxOpen, setLightboxOpen] = useState(false);
@@ -165,6 +163,9 @@ export function VideoBlock({
165
163
  const resizeStateRef = useRef<VideoResizeState | null>(null);
166
164
  const isEditable = editor.isEditable;
167
165
  const src = node.attrs.src as string;
166
+ const sourcePanelOpen = node.attrs.sourcePanelOpen === true;
167
+ const sourceTab: VideoSourceTab =
168
+ node.attrs.sourceTab === "link" ? "link" : "upload";
168
169
  const poster = (node.attrs.poster as string) || "";
169
170
  const isUploading = Boolean(node.attrs.uploadId);
170
171
  const width = normalizedVideoWidth(node.attrs.width);
@@ -172,6 +173,14 @@ export function VideoBlock({
172
173
  const controlsVisible = isEditable && (isHovered || selected);
173
174
  const options = extension.options as ContentVideoOptions;
174
175
 
176
+ function setSourcePanelOpen(open: boolean) {
177
+ updateAttributes({ sourcePanelOpen: open });
178
+ }
179
+
180
+ function setSourceTab(tab: VideoSourceTab) {
181
+ updateAttributes({ sourcePanelOpen: true, sourceTab: tab });
182
+ }
183
+
175
184
  useEffect(() => {
176
185
  if (!sourcePanelOpen && !selected) return;
177
186
 
@@ -210,10 +219,9 @@ export function VideoBlock({
210
219
  }
211
220
 
212
221
  function openReplacePanel() {
213
- setSourceTab("upload");
214
222
  setVideoUrl("");
215
223
  setSourcePanelDismissed(false);
216
- setSourcePanelOpen(true);
224
+ updateAttributes({ sourcePanelOpen: true, sourceTab: "upload" });
217
225
  }
218
226
 
219
227
  function handleLightboxOpenChange(open: boolean) {
@@ -376,8 +384,11 @@ export function VideoBlock({
376
384
  const toastId = toast.loading(t("editor.media.uploadingVideo"));
377
385
  try {
378
386
  const nextSrc = await uploadVideoFile(file);
379
- updateAttributes({ src: nextSrc });
380
- setSourcePanelOpen(false);
387
+ updateAttributes({
388
+ src: nextSrc,
389
+ sourcePanelOpen: false,
390
+ sourceTab: "upload",
391
+ });
381
392
  toast.success(t("editor.media.videoAdded"), { id: toastId });
382
393
  } catch (error) {
383
394
  toast.error(videoUploadErrorMessage(error), { id: toastId });
@@ -399,9 +410,12 @@ export function VideoBlock({
399
410
  return;
400
411
  }
401
412
 
402
- updateAttributes({ src: nextSrc });
413
+ updateAttributes({
414
+ src: nextSrc,
415
+ sourcePanelOpen: false,
416
+ sourceTab: "upload",
417
+ });
403
418
  setVideoUrl("");
404
- setSourcePanelOpen(false);
405
419
  }
406
420
 
407
421
  function renderSourcePanel(replace = false) {
@@ -417,6 +431,11 @@ export function VideoBlock({
417
431
  role="tab"
418
432
  aria-selected={sourceTab === "upload"}
419
433
  className="media-source-panel__tab"
434
+ onPointerDown={(event) => {
435
+ event.preventDefault();
436
+ event.stopPropagation();
437
+ setSourceTab("upload");
438
+ }}
420
439
  onClick={() => setSourceTab("upload")}
421
440
  >
422
441
  {t("editor.media.upload")}
@@ -426,6 +445,11 @@ export function VideoBlock({
426
445
  role="tab"
427
446
  aria-selected={sourceTab === "link"}
428
447
  className="media-source-panel__tab"
448
+ onPointerDown={(event) => {
449
+ event.preventDefault();
450
+ event.stopPropagation();
451
+ setSourceTab("link");
452
+ }}
429
453
  onClick={() => setSourceTab("link")}
430
454
  >
431
455
  {t("editor.media.link")}
@@ -114,6 +114,20 @@ export const VideoNode = Node.create<ContentVideoOptions>({
114
114
  parseHTML: () => null,
115
115
  renderHTML: () => ({}),
116
116
  },
117
+ // UI-only state. Keeping the source panel on the ProseMirror node makes
118
+ // it survive React node-view remounts while the empty video draft is
119
+ // being autosaved/reconciled. It is deliberately omitted from HTML and
120
+ // Markdown serialization.
121
+ sourcePanelOpen: {
122
+ default: false,
123
+ parseHTML: () => false,
124
+ renderHTML: () => ({}),
125
+ },
126
+ sourceTab: {
127
+ default: "upload",
128
+ parseHTML: () => "upload",
129
+ renderHTML: () => ({}),
130
+ },
117
131
  };
118
132
  },
119
133
 
@@ -104,10 +104,13 @@ export function buildRegistrySlashItems(
104
104
  // not a content-authoring block.
105
105
  // - `inline-database` is registered in Phase 2 for render/round-trip
106
106
  // compatibility; Phase 3 owns the `/database` insertion flow.
107
+ // - `callout` duplicates Content's native Notion-style Callout command.
108
+ // Keep one unambiguous authoring choice; the registry remains available
109
+ // for rendering and round-tripping saved `<Callout>` blocks.
107
110
  // - `source-component` is emitted by provider hydration to preserve
108
111
  // source-native blocks; users should not author raw preservation
109
112
  // markers by hand.
110
- // The genuinely document-friendly rich blocks (callout, decision, diagram,
113
+ // The genuinely document-friendly rich blocks (decision, diagram,
111
114
  // wireframe, and the dev-doc/structured set) ARE offered.
112
115
  includeSpec: (spec) =>
113
116
  ![
@@ -115,6 +118,7 @@ export function buildRegistrySlashItems(
115
118
  "question-form",
116
119
  "visual-questions",
117
120
  "inline-database",
121
+ "callout",
118
122
  "source-component",
119
123
  ].includes(spec.type),
120
124
  toItem: (spec, insert) => ({
@@ -170,6 +170,57 @@ export function writeContentDatabaseResponseToCache(
170
170
  );
171
171
  }
172
172
 
173
+ export function applyOptimisticBuilderWriteMode(
174
+ current: ContentDatabaseResponse | undefined,
175
+ request: SetContentDatabaseSourceWriteModeRequest,
176
+ ) {
177
+ if (!current || !request.writeMode) return current;
178
+ const sourceId = request.sourceId ?? current.source?.id;
179
+ if (!sourceId) return current;
180
+ const writeMode = request.writeMode;
181
+ const liveWritesEnabled = writeMode !== "read_only";
182
+ const allowPublicationTransitions =
183
+ writeMode === "publish_updates" &&
184
+ request.allowPublicationTransitions === true;
185
+ const allowedWriteModes =
186
+ writeMode === "publish_updates"
187
+ ? (["autosave", "publish"] as const)
188
+ : writeMode === "stage_only"
189
+ ? (["autosave"] as const)
190
+ : ([] as const);
191
+ const patchSource = (
192
+ source: ContentDatabaseResponse["source"],
193
+ ): ContentDatabaseResponse["source"] =>
194
+ source?.id === sourceId
195
+ ? {
196
+ ...source,
197
+ capabilities: {
198
+ ...source.capabilities,
199
+ liveWritesEnabled,
200
+ },
201
+ metadata: {
202
+ ...source.metadata,
203
+ writeMode,
204
+ allowPublicationTransitions,
205
+ allowedWriteModes: [...allowedWriteModes],
206
+ allowDraftWrites: false,
207
+ allowPublishWrites: writeMode === "publish_updates",
208
+ pushMode:
209
+ writeMode === "publish_updates"
210
+ ? "publish"
211
+ : writeMode === "stage_only"
212
+ ? "autosave"
213
+ : "none",
214
+ },
215
+ }
216
+ : source;
217
+ return {
218
+ ...current,
219
+ source: patchSource(current.source),
220
+ sources: current.sources?.map((source) => patchSource(source)!),
221
+ };
222
+ }
223
+
173
224
  export function applyDocumentPropertyValueToDatabaseResponse(
174
225
  current: ContentDatabaseResponse | undefined,
175
226
  patch: {
@@ -679,7 +730,12 @@ export function useAddDatabaseItem(documentId: string) {
679
730
  return useActionMutation<ContentDatabaseResponse, AddDatabaseItemRequest>(
680
731
  "add-database-item",
681
732
  {
682
- onSuccess: () => {
733
+ onSuccess: (data) => {
734
+ // The action returns the committed row and full database snapshot.
735
+ // Seed every active pagination key before invalidating so navigating
736
+ // away from the creation side-peek cannot briefly lose an appended row
737
+ // behind an older 100/200-row response.
738
+ writeContentDatabaseResponseToCache(queryClient, documentId, data);
683
739
  queryClient.invalidateQueries({
684
740
  queryKey: contentDatabaseQueryKey(documentId),
685
741
  });
@@ -1218,7 +1274,8 @@ export function useSetContentDatabaseSourceWriteMode(documentId: string) {
1218
1274
  ContentDatabaseResponse,
1219
1275
  SetContentDatabaseSourceWriteModeRequest
1220
1276
  >("set-content-database-source-write-mode", {
1221
- onSuccess: () => {
1277
+ onSuccess: (data) => {
1278
+ writeContentDatabaseResponseToCache(queryClient, documentId, data);
1222
1279
  queryClient.invalidateQueries({
1223
1280
  queryKey: contentDatabaseQueryKey(documentId),
1224
1281
  });
@@ -18,9 +18,6 @@ import type { QueryClient } from "@tanstack/react-query";
18
18
  import { useQueryClient } from "@tanstack/react-query";
19
19
  import { toast } from "sonner";
20
20
 
21
- import { databaseItemBodyHydrationIsPending } from "@/components/editor/body-hydration";
22
- import { isEffectivelyEmptyDocumentContent } from "@/components/editor/body-hydration";
23
-
24
21
  import type { DocumentUpdateConflictResponse } from "../../actions/update-document";
25
22
  import {
26
23
  removeOptimisticItemFromContentDatabase,
@@ -243,28 +240,12 @@ export function seedDatabaseItemDocumentCaches(
243
240
  queryClient: Pick<QueryClient, "getQueryData" | "setQueryData">,
244
241
  item: ContentDatabaseItem,
245
242
  ) {
246
- const sourceBackedEmptyBody =
247
- (!!item.bodyHydration || !!item.document.databaseMembership?.sourceId) &&
248
- isEffectivelyEmptyDocumentContent(item.document.content);
249
- // Seed only cold caches. Overwriting an existing entry would bump its
250
- // freshness with possibly older table-snapshot data (a background database
251
- // refetch can lag a just-saved document edit) and suppress the correcting
252
- // refetch for the whole staleTime window. Source-backed rows are never seeded:
253
- // list snapshots are not authoritative enough to unlock the body editor, even
254
- // when they happen to contain non-empty content. The dedicated get-document
255
- // response owns that decision and prevents an edit from racing hydration.
256
- if (
257
- !databaseItemBodyHydrationIsPending(item) &&
258
- !sourceBackedEmptyBody &&
259
- !item.bodyHydration &&
260
- !item.document.databaseMembership?.sourceId &&
261
- queryClient.getQueryData(documentQueryKey(item.document.id)) === undefined
262
- ) {
263
- queryClient.setQueryData<Document>(documentQueryKey(item.document.id), {
264
- ...item.document,
265
- properties: item.properties,
266
- });
267
- }
243
+ // Database table responses are list snapshots, not authoritative editable
244
+ // bodies. Even a cold cache can race a just-saved collaborative edit: seeding
245
+ // it marks the row snapshot fresh and can mount ProseMirror before the
246
+ // dedicated get-document request returns. Keep document bodies exclusively
247
+ // owned by get-document; the table may still warm the separately scoped
248
+ // property cache below.
268
249
  if (
269
250
  queryClient.getQueryData(documentPropertiesQueryKey(item.document.id)) ===
270
251
  undefined
@@ -289,12 +270,23 @@ export function useDocuments() {
289
270
  });
290
271
  }
291
272
 
273
+ export const DOCUMENT_QUERY_FRESHNESS_OPTIONS = {
274
+ // Database/list snapshots may seed this cache before the page opens. Their
275
+ // body can lag a just-saved collaborative edit, so never treat that seed as
276
+ // authoritative for mounting the editor. The dedicated get-document action
277
+ // must win once per page mount; subsequent background refetches can keep the
278
+ // already-mounted editor current without remounting it.
279
+ staleTime: 0,
280
+ refetchOnMount: "always" as const,
281
+ retry: false,
282
+ };
283
+
292
284
  export function useDocument(id: string | null) {
293
285
  return useActionQuery<Document>("get-document", id ? { id } : undefined, {
294
286
  enabled: !!id,
295
287
  // Doc-not-found / no-access errors are deterministic — retrying just keeps
296
288
  // the spinner up for ~7s before the UI can render "Not found".
297
- retry: false,
289
+ ...DOCUMENT_QUERY_FRESHNESS_OPTIONS,
298
290
  });
299
291
  }
300
292
 
@@ -566,12 +566,7 @@ export default function Root() {
566
566
  const [cmdkOpen, setCmdkOpen] = useState(false);
567
567
  const location = useLocation();
568
568
  const loaderData = useLoaderData<typeof loader>();
569
- useCommandMenuShortcut(
570
- useCallback(() => setCmdkOpen(true), []),
571
- {
572
- allowContentEditable: true,
573
- },
574
- );
569
+ useCommandMenuShortcut(useCallback(() => setCmdkOpen(true), []));
575
570
 
576
571
  // Public document paths (/p/*) SSR real content without the ClientOnly gate
577
572
  // so crawlers and unauthenticated visitors receive full markup on first visit.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-24
4
+ ---
5
+
6
+ Builder can now publish approved updates to entries that are already live.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-24
4
+ ---
5
+
6
+ Builder collection loading no longer restarts from the beginning when overlapping refreshes finish out of order.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-24
4
+ ---
5
+
6
+ Builder connections now complete securely from Netlify deploy previews.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-24
4
+ ---
5
+
6
+ Builder draft creation now scopes execution to the selected article, avoiding hosted timeouts on large synced collections.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-24
4
+ ---
5
+
6
+ Builder review now distinguishes preparing a safe dry run from sending the confirmed update to Builder.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-24
4
+ ---
5
+
6
+ Builder source imports now recover from a transient pagination failure without discarding already loaded rows.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-24
4
+ ---
5
+
6
+ Builder source refresh now preserves the provider-bound field when local properties share the same label, so follow-up edits remain reviewable.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-24
4
+ ---
5
+
6
+ Builder update reviews now open reliably on large collections by loading full article details only for pending changes.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-24
4
+ ---
5
+
6
+ Builder write policy controls now reflect successful changes immediately.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-24
4
+ ---
5
+
6
+ Date properties now save reliably when selected with the native date picker.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-24
4
+ ---
5
+
6
+ Editor slash search now keeps multi-word block names such as Heading 2 open instead of inserting them as literal text.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-24
4
+ ---
5
+
6
+ Exact editor slash commands now execute on Enter even if the command menu fails to appear.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-24
4
+ ---
5
+
6
+ New collaborative pages now save their first text and media edits before you navigate away.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-24
4
+ ---
5
+
6
+ New local Builder rows no longer remain locked behind a nonexistent body sync.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-24
4
+ ---
5
+
6
+ Opening or closing a collaborative document no longer lets unfocused editor normalization overwrite saved rich content.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-24
4
+ ---
5
+
6
+ Selected text now opens the link editor with Command-K or Control-K instead of opening global search.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-24
4
+ ---
5
+
6
+ Code Block and other slash-menu choices now finish without hanging the collaborative editor, even when closing the menu unmounts the selected choice.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-24
4
+ ---
5
+
6
+ Rich document edits, including uploaded and embedded media, now stay intact while collaborative drafts save.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-24
4
+ ---
5
+
6
+ Video link insertion now keeps its source panel open while the editor reconciles.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-26
4
+ ---
5
+
6
+ Builder publishing now shows safe validation details instead of a generic server error.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-26
4
+ ---
5
+
6
+ Builder reviews stay responsive on large collections and preserve refresh progress when source settings change