@agent-native/core 0.90.1 → 0.90.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 (295) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +14 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/client/AgentPanel.tsx +1 -1
  5. package/corpus/core/src/client/rich-markdown-editor/useCollabReconcile.ts +11 -6
  6. package/corpus/core/src/client/use-action.ts +39 -2
  7. package/corpus/core/src/client/use-db-sync.ts +44 -18
  8. package/corpus/core/src/db/create-get-db.ts +32 -2
  9. package/corpus/core/src/server/framework-request-handler.ts +52 -4
  10. package/corpus/templates/assets/.agents/skills/asset-generation/SKILL.md +5 -0
  11. package/corpus/templates/assets/.agents/skills/logo-composite/SKILL.md +34 -6
  12. package/corpus/templates/assets/AGENTS.md +23 -4
  13. package/corpus/templates/assets/actions/_generation-preset-settings.ts +48 -0
  14. package/corpus/templates/assets/actions/_helpers.ts +8 -1
  15. package/corpus/templates/assets/actions/_preset-skeleton-validation.ts +64 -0
  16. package/corpus/templates/assets/actions/create-generation-preset.ts +11 -3
  17. package/corpus/templates/assets/actions/generate-image-batch.ts +7 -2
  18. package/corpus/templates/assets/actions/generate-image.ts +342 -25
  19. package/corpus/templates/assets/actions/get-library.ts +4 -3
  20. package/corpus/templates/assets/actions/navigate.ts +2 -1
  21. package/corpus/templates/assets/actions/refresh-generation-run.ts +5 -1
  22. package/corpus/templates/assets/actions/update-asset.ts +1 -0
  23. package/corpus/templates/assets/actions/update-generation-preset.ts +8 -1
  24. package/corpus/templates/assets/actions/view-screen.ts +8 -1
  25. package/corpus/templates/assets/app/components/generation/GenerationResults.tsx +9 -1
  26. package/corpus/templates/assets/app/hooks/use-image-model-menu.ts +1 -0
  27. package/corpus/templates/assets/app/hooks/use-navigation-state.ts +11 -0
  28. package/corpus/templates/assets/app/i18n/zh-TW.ts +64 -0
  29. package/corpus/templates/assets/app/i18n-data.ts +650 -0
  30. package/corpus/templates/assets/app/routes/asset.$id.tsx +2 -1
  31. package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +44 -33
  32. package/corpus/templates/assets/app/routes/brand-kits.$id_.presets.$presetId.tsx +1474 -0
  33. package/corpus/templates/assets/app/routes/library.tsx +43 -1
  34. package/corpus/templates/assets/server/lib/generation.ts +366 -44
  35. package/corpus/templates/assets/server/lib/image-processing.ts +252 -0
  36. package/corpus/templates/assets/server/lib/preset-skeleton.ts +137 -0
  37. package/corpus/templates/assets/shared/api.ts +47 -0
  38. package/corpus/templates/clips/app/components/library/library-layout.tsx +7 -2
  39. package/corpus/templates/clips/app/components/library/sort-menu.tsx +1 -1
  40. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +114 -33
  41. package/corpus/templates/clips/app/routes/_app.library._index.tsx +27 -1
  42. package/corpus/templates/clips/app/routes/record.tsx +157 -68
  43. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +5 -5
  44. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +20 -3
  45. package/corpus/templates/clips/shared/finalize-recovery.ts +23 -3
  46. package/corpus/templates/content/AGENTS.md +52 -52
  47. package/corpus/templates/content/actions/_builder-cms-read-client.ts +188 -8
  48. package/corpus/templates/content/actions/_builder-docs-client.ts +41 -3
  49. package/corpus/templates/content/actions/_database-source-utils.ts +998 -160
  50. package/corpus/templates/content/actions/_database-utils.ts +44 -4
  51. package/corpus/templates/content/actions/_notion-action-utils.ts +6 -2
  52. package/corpus/templates/content/actions/add-content-database-source-field-property.ts +23 -1
  53. package/corpus/templates/content/actions/attach-content-database-source.ts +85 -12
  54. package/corpus/templates/content/actions/change-content-database-source-role.ts +9 -1
  55. package/corpus/templates/content/actions/delete-content-database.ts +1 -0
  56. package/corpus/templates/content/actions/get-document.ts +11 -2
  57. package/corpus/templates/content/actions/list-content-databases.ts +57 -9
  58. package/corpus/templates/content/actions/prepare-builder-source-review.ts +23 -6
  59. package/corpus/templates/content/actions/refresh-content-database-source.ts +26 -3
  60. package/corpus/templates/content/actions/restore-content-database.ts +1 -0
  61. package/corpus/templates/content/actions/update-document.ts +43 -0
  62. package/corpus/templates/content/app/components/editor/BuilderBodySyncingNotice.tsx +21 -0
  63. package/corpus/templates/content/app/components/editor/DocumentDatabase.tsx +0 -1
  64. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +70 -28
  65. package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +69 -17
  66. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +4 -4
  67. package/corpus/templates/content/app/components/editor/body-hydration.ts +112 -0
  68. package/corpus/templates/content/app/components/editor/builder-body-hydration-pump.ts +52 -0
  69. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +9076 -2876
  70. package/corpus/templates/content/app/components/editor/database-sources/BuilderSourceReviewDialog.tsx +41 -1
  71. package/corpus/templates/content/app/components/editor/extensions/ImageBlock.tsx +36 -11
  72. package/corpus/templates/content/app/components/editor/previewDocumentSaveController.ts +21 -1
  73. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +11 -1
  74. package/corpus/templates/content/app/components/sidebar/DocumentTreeItem.tsx +11 -8
  75. package/corpus/templates/content/app/global.css +41 -0
  76. package/corpus/templates/content/app/hooks/use-content-database.ts +346 -42
  77. package/corpus/templates/content/app/hooks/use-db-sync.ts +9 -0
  78. package/corpus/templates/content/app/hooks/use-documents.ts +47 -0
  79. package/corpus/templates/content/app/hooks/use-notion.ts +12 -10
  80. package/corpus/templates/content/app/i18n/zh-TW.ts +35 -0
  81. package/corpus/templates/content/app/i18n-data.ts +355 -0
  82. package/corpus/templates/content/app/root.tsx +22 -0
  83. package/corpus/templates/content/changelog/2026-07-01-builder-database-sources-keep-loading-rows-in-the-background.md +6 -0
  84. package/corpus/templates/content/changelog/2026-07-01-builder-source-attach-starts-with-usable-rows.md +6 -0
  85. package/corpus/templates/content/changelog/2026-07-01-builder-source-attachment-now-stays-connected-after-large.md +6 -0
  86. package/corpus/templates/content/changelog/2026-07-01-builder-source-refreshes-now-show-progress-for-large-docs-blog.md +6 -0
  87. package/corpus/templates/content/changelog/2026-07-01-database-pages-now-delete-to-trash-without-route-errors.md +6 -0
  88. package/corpus/templates/content/changelog/2026-07-02-builder-source-refreshes-recover-from-stalled-background-row.md +6 -0
  89. package/corpus/templates/content/changelog/2026-07-02-builder-sourced-rows-open-with-sync-protection.md +6 -0
  90. package/corpus/templates/content/changelog/2026-07-02-database-rows-and-pages-open-faster-from-recently-loaded-dat.md +6 -0
  91. package/corpus/templates/content/changelog/2026-07-02-preview-panels-close-reliably-narrow-sidebar-row-actions-sta.md +6 -0
  92. package/corpus/templates/content/changelog/2026-07-06-builder-sync-progress-no-longer-shows-continue.md +6 -0
  93. package/corpus/templates/content/shared/api.ts +13 -0
  94. package/corpus/templates/content/shared/builder-mdx.ts +16 -3
  95. package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +23 -13
  96. package/corpus/templates/design/.agents/skills/responsive-breakpoints/SKILL.md +98 -0
  97. package/corpus/templates/design/.agents/skills/shader-fills/SKILL.md +162 -0
  98. package/corpus/templates/design/AGENTS.md +9 -2
  99. package/corpus/templates/design/actions/add-breakpoint.ts +6 -3
  100. package/corpus/templates/design/actions/apply-a11y-fix.ts +57 -37
  101. package/corpus/templates/design/actions/apply-component-prop-edit.ts +41 -20
  102. package/corpus/templates/design/actions/apply-motion-edit.ts +251 -38
  103. package/corpus/templates/design/actions/apply-shader-fill.ts +90 -66
  104. package/corpus/templates/design/actions/apply-visual-edit.ts +282 -55
  105. package/corpus/templates/design/actions/create-component.ts +29 -60
  106. package/corpus/templates/design/actions/create-file.ts +9 -2
  107. package/corpus/templates/design/actions/duplicate-design.ts +31 -2
  108. package/corpus/templates/design/actions/edit-design.ts +36 -38
  109. package/corpus/templates/design/actions/generate-design-title.ts +87 -0
  110. package/corpus/templates/design/actions/generate-design.ts +53 -18
  111. package/corpus/templates/design/actions/generate-screens.ts +108 -4
  112. package/corpus/templates/design/actions/get-motion-timeline.ts +35 -7
  113. package/corpus/templates/design/actions/insert-asset.ts +34 -29
  114. package/corpus/templates/design/actions/insert-design-native-asset.ts +129 -32
  115. package/corpus/templates/design/actions/insert-figma-library-asset.ts +35 -30
  116. package/corpus/templates/design/actions/present-design-variants.ts +7 -2
  117. package/corpus/templates/design/actions/remove-motion-timeline.ts +31 -36
  118. package/corpus/templates/design/actions/update-file.ts +190 -75
  119. package/corpus/templates/design/app/components/design/BreakpointBar.tsx +403 -0
  120. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +469 -222
  121. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +708 -53
  122. package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +83 -3
  123. package/corpus/templates/design/app/components/design/EditPanel.tsx +1091 -6948
  124. package/corpus/templates/design/app/components/design/LayersPanel.tsx +419 -85
  125. package/corpus/templates/design/app/components/design/MotionDock.tsx +1124 -103
  126. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +2610 -1398
  127. package/corpus/templates/design/app/components/design/ReadOnlyDesignBanner.tsx +22 -0
  128. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +2182 -235
  129. package/corpus/templates/design/app/components/design/bridge/motion-preview.bridge.ts +187 -11
  130. package/corpus/templates/design/app/components/design/bridge/shader-fill-preview.bridge.ts +376 -1
  131. package/corpus/templates/design/app/components/design/bridge/shader-runtime.bridge.ts +746 -0
  132. package/corpus/templates/design/app/components/design/canvas-primitive-style.ts +17 -0
  133. package/corpus/templates/design/app/components/design/code-workbench/SideBar.tsx +1 -1
  134. package/corpus/templates/design/app/components/design/code-workbench/explorer/FileTree.tsx +1 -3
  135. package/corpus/templates/design/app/components/design/code-workbench/quickinput/QuickInput.tsx +1 -1
  136. package/corpus/templates/design/app/components/design/edit-panel/appearance-properties.tsx +518 -0
  137. package/corpus/templates/design/app/components/design/edit-panel/code-inspect-helpers.tsx +562 -0
  138. package/corpus/templates/design/app/components/design/edit-panel/component-section.tsx +763 -0
  139. package/corpus/templates/design/app/components/design/edit-panel/document-colors.ts +94 -0
  140. package/corpus/templates/design/app/components/design/edit-panel/effects-properties.tsx +780 -0
  141. package/corpus/templates/design/app/components/design/edit-panel/element-classification.ts +446 -0
  142. package/corpus/templates/design/app/components/design/edit-panel/element-identity.ts +79 -0
  143. package/corpus/templates/design/app/components/design/edit-panel/field-primitives.tsx +315 -0
  144. package/corpus/templates/design/app/components/design/edit-panel/fill-gradient-helpers.ts +344 -0
  145. package/corpus/templates/design/app/components/design/edit-panel/fill-properties.tsx +594 -0
  146. package/corpus/templates/design/app/components/design/edit-panel/frame-presets-panel.tsx +119 -0
  147. package/corpus/templates/design/app/components/design/edit-panel/inspector-controls.tsx +248 -0
  148. package/corpus/templates/design/app/components/design/edit-panel/interaction-state-helpers.ts +45 -0
  149. package/corpus/templates/design/app/components/design/edit-panel/layout-properties.tsx +693 -0
  150. package/corpus/templates/design/app/components/design/edit-panel/panel-primitives.tsx +724 -0
  151. package/corpus/templates/design/app/components/design/edit-panel/position-helpers.ts +207 -0
  152. package/corpus/templates/design/app/components/design/edit-panel/position-layout-properties.tsx +628 -0
  153. package/corpus/templates/design/app/components/design/edit-panel/selection-helpers.ts +91 -0
  154. package/corpus/templates/design/app/components/design/edit-panel/stroke-properties.tsx +649 -0
  155. package/corpus/templates/design/app/components/design/edit-panel/style-change-types.ts +118 -0
  156. package/corpus/templates/design/app/components/design/edit-panel/style-options.ts +88 -0
  157. package/corpus/templates/design/app/components/design/edit-panel/transform-helpers.ts +100 -0
  158. package/corpus/templates/design/app/components/design/edit-panel/typography-helpers.ts +117 -0
  159. package/corpus/templates/design/app/components/design/edit-panel/typography-properties.tsx +501 -0
  160. package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +91 -40
  161. package/corpus/templates/design/app/components/design/inspector/BreakpointOverrideIndicator.tsx +82 -0
  162. package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +189 -87
  163. package/corpus/templates/design/app/components/design/inspector/GlslShaderPanel.tsx +1097 -0
  164. package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +44 -0
  165. package/corpus/templates/design/app/components/design/inspector/InteractionStatePanel.tsx +258 -0
  166. package/corpus/templates/design/app/components/design/inspector/MotionKeyframeDiamond.tsx +144 -0
  167. package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +99 -9
  168. package/corpus/templates/design/app/components/design/inspector/frame-size-presets.ts +116 -0
  169. package/corpus/templates/design/app/components/design/inspector/index.ts +26 -0
  170. package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +29 -0
  171. package/corpus/templates/design/app/components/design/multi-screen/alt-hover-measurement.ts +171 -0
  172. package/corpus/templates/design/app/components/design/multi-screen/board-surface-html.ts +220 -0
  173. package/corpus/templates/design/app/components/design/multi-screen/chrome-transitions.ts +35 -0
  174. package/corpus/templates/design/app/components/design/multi-screen/cross-screen-drop.ts +134 -0
  175. package/corpus/templates/design/app/components/design/multi-screen/culling.ts +185 -0
  176. package/corpus/templates/design/app/components/design/multi-screen/gradient-overlay-geometry.ts +120 -0
  177. package/corpus/templates/design/app/components/design/multi-screen/types.ts +892 -0
  178. package/corpus/templates/design/app/components/design/multi-screen/vector-edit-geometry.ts +21 -0
  179. package/corpus/templates/design/app/components/design/types.ts +15 -0
  180. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +109 -5
  181. package/corpus/templates/design/app/global.css +8 -8
  182. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +259 -2
  183. package/corpus/templates/design/app/i18n/zh-TW.ts +163 -9
  184. package/corpus/templates/design/app/i18n-breakpoints.ts +205 -0
  185. package/corpus/templates/design/app/i18n-data.ts +1664 -152
  186. package/corpus/templates/design/app/i18n-motion.ts +563 -0
  187. package/corpus/templates/design/app/lib/design-import.ts +73 -0
  188. package/corpus/templates/design/app/pages/Index.tsx +41 -22
  189. package/corpus/templates/design/changelog/2026-06-29-design-inspector-controls-now-match-figmas-softer-dark-chrome.md +1 -1
  190. package/corpus/templates/design/changelog/2026-06-30-design-now-has-a-figma-style-left-rail-for-file-agent-assets.md +1 -1
  191. package/corpus/templates/design/changelog/2026-06-30-design-tools-now-use-a-quieter-figma-style-list-layout.md +1 -1
  192. package/corpus/templates/design/changelog/2026-06-30-multi-select-outlines-now-stay-consistent-across-all-screens.md +1 -1
  193. package/corpus/templates/design/changelog/2026-07-03-canvas-interactions-now-match-figma-rotation-aware-resizing-.md +1 -1
  194. package/corpus/templates/design/changelog/2026-07-03-layers-panel-matches-figma-top-layer-on-top-drag-with-auto-s.md +1 -1
  195. package/corpus/templates/design/changelog/2026-07-05-designs-get-ai-generated-names-from-your-prompt.md +6 -0
  196. package/corpus/templates/design/changelog/2026-07-05-local-code-screens-keep-their-connection-when-duplicated-and.md +6 -0
  197. package/corpus/templates/design/changelog/2026-07-05-press-a-to-draw-screens-on-the-canvas-inside-a-screen-it-dr.md +6 -0
  198. package/corpus/templates/design/changelog/2026-07-06-3d-rotation-and-perspective-controls-on-every-element.md +6 -0
  199. package/corpus/templates/design/changelog/2026-07-06-ai-generated-and-duplicated-screens-now-get-their-editor-sel.md +6 -0
  200. package/corpus/templates/design/changelog/2026-07-06-applying-shaders-and-fills-in-quick-succession-can-no-longer.md +6 -0
  201. package/corpus/templates/design/changelog/2026-07-06-breakpoint-frames-in-the-overview-now-support-click-to-selec.md +6 -0
  202. package/corpus/templates/design/changelog/2026-07-06-breakpoint-segments-in-the-inspector-now-show-a-device-icon-.md +6 -0
  203. package/corpus/templates/design/changelog/2026-07-06-breakpoint-targeting-now-lives-in-one-compact-control-in-the.md +6 -0
  204. package/corpus/templates/design/changelog/2026-07-06-canvas-edits-can-no-longer-be-overwritten-by-stale-collabora.md +6 -0
  205. package/corpus/templates/design/changelog/2026-07-06-canvas-edits-inside-screens-save-reliably-again.md +6 -0
  206. package/corpus/templates/design/changelog/2026-07-06-cleaner-inspector-removed-the-ask-ai-box-from-the-design-tab.md +6 -0
  207. package/corpus/templates/design/changelog/2026-07-06-clicking-empty-canvas-space-now-deselects-an-element-inside-.md +6 -0
  208. package/corpus/templates/design/changelog/2026-07-06-dragging-an-element-onto-a-rectangle-now-nests-it-inside-wit.md +6 -0
  209. package/corpus/templates/design/changelog/2026-07-06-dragging-screens-and-objects-on-the-canvas-is-now-much-smoot.md +6 -0
  210. package/corpus/templates/design/changelog/2026-07-06-drawing-a-shape-or-text-on-the-canvas-no-longer-flashes-away.md +6 -0
  211. package/corpus/templates/design/changelog/2026-07-06-dropping-an-element-between-two-others-inside-a-screen-now-s.md +6 -0
  212. package/corpus/templates/design/changelog/2026-07-06-duplicating-a-screen-now-places-the-copy-exactly-where-you-d.md +6 -0
  213. package/corpus/templates/design/changelog/2026-07-06-edit-gradients-directly-on-elements-inside-screens-scale-str.md +6 -0
  214. package/corpus/templates/design/changelog/2026-07-06-edits-from-collaborators-and-the-agent-now-update-the-canvas.md +6 -0
  215. package/corpus/templates/design/changelog/2026-07-06-fixed-a-bug-where-most-style-position-and-text-edits-briefly.md +6 -0
  216. package/corpus/templates/design/changelog/2026-07-06-fixed-a-confusing-raw-error-message-when-a-file-upload-fails.md +6 -0
  217. package/corpus/templates/design/changelog/2026-07-06-fixed-a-rare-case-where-an-edit-could-be-silently-overwritte.md +6 -0
  218. package/corpus/templates/design/changelog/2026-07-06-fixed-inserted-assets-sometimes-disappearing-reappearing-or-.md +6 -0
  219. package/corpus/templates/design/changelog/2026-07-06-fixed-inspector-value-scrubbing-producing-erratic-numbers-an.md +6 -0
  220. package/corpus/templates/design/changelog/2026-07-06-fixed-padding-gap-and-min-max-size-scrubbing-not-updating-th.md +6 -0
  221. package/corpus/templates/design/changelog/2026-07-06-fixed-text-stroke-color-turning-black-and-glyphs-disappearin.md +6 -0
  222. package/corpus/templates/design/changelog/2026-07-06-fixed-the-collapsed-effects-and-stroke-inspector-sections-sh.md +6 -0
  223. package/corpus/templates/design/changelog/2026-07-06-fixed-the-new-design-dialog-closing-unexpectedly-when-using-.md +6 -0
  224. package/corpus/templates/design/changelog/2026-07-06-fixed-the-typography-section-missing-when-selecting-text-nes.md +6 -0
  225. package/corpus/templates/design/changelog/2026-07-06-full-view-no-longer-flashes-back-to-the-overview-on-entry-no.md +6 -0
  226. package/corpus/templates/design/changelog/2026-07-06-keyframe-animation-timeline-per-property-keyframes-easing-cu.md +6 -0
  227. package/corpus/templates/design/changelog/2026-07-06-moving-restyling-and-scrubbing-values-on-elements-in-ai-gene.md +6 -0
  228. package/corpus/templates/design/changelog/2026-07-06-padding-and-corner-radius-value-scrubbing-now-snaps-to-whole.md +6 -0
  229. package/corpus/templates/design/changelog/2026-07-06-padding-handles-now-only-resize-on-the-handle-line-itself-sh.md +6 -0
  230. package/corpus/templates/design/changelog/2026-07-06-preview-and-edit-hover-focus-and-pressed-states-with-real-cs.md +6 -0
  231. package/corpus/templates/design/changelog/2026-07-06-promoting-an-element-to-a-component-now-works-correctly-for-.md +6 -0
  232. package/corpus/templates/design/changelog/2026-07-06-reduced-url-history-churn-and-selection-overlay-flicker-whil.md +6 -0
  233. package/corpus/templates/design/changelog/2026-07-06-removed-the-decorative-dot-before-screen-names-in-the-overvi.md +6 -0
  234. package/corpus/templates/design/changelog/2026-07-06-responsive-breakpoints-edit-at-any-width-with-cascading-over.md +6 -0
  235. package/corpus/templates/design/changelog/2026-07-06-screen-labels-no-longer-turn-blue-when-you-hover-inside-the-.md +6 -0
  236. package/corpus/templates/design/changelog/2026-07-06-scrolling-a-screen-with-an-element-selected-stays-smooth-on-.md +6 -0
  237. package/corpus/templates/design/changelog/2026-07-06-selecting-multiple-elements-and-dragging-now-moves-the-whole.md +6 -0
  238. package/corpus/templates/design/changelog/2026-07-06-selection-borders-handles-and-value-readouts-now-stay-the-sa.md +6 -0
  239. package/corpus/templates/design/changelog/2026-07-06-selection-handles-and-editing-chrome-now-stay-a-constant-siz.md +6 -0
  240. package/corpus/templates/design/changelog/2026-07-06-shader-fills-and-effects-ai-authored-or-preset-glsl-shaders-.md +6 -0
  241. package/corpus/templates/design/changelog/2026-07-06-text-drawn-on-the-canvas-now-defaults-to-white-and-inter-in-.md +6 -0
  242. package/corpus/templates/design/changelog/2026-07-06-text-dropped-into-a-shape-now-stays-readable-instead-of-disa.md +6 -0
  243. package/corpus/templates/design/changelog/2026-07-06-the-add-tweak-controls-prompt-no-longer-jumps-to-the-corner-.md +6 -0
  244. package/corpus/templates/design/changelog/2026-07-06-the-padding-value-readout-now-stays-visible-while-you-hover-.md +6 -0
  245. package/corpus/templates/design/changelog/2026-07-06-the-selected-element-attachment-now-clears-from-the-chat-com.md +6 -0
  246. package/corpus/templates/design/changelog/2026-07-06-the-zoom-menu-is-more-compact-with-tight-rows-and-right-alig.md +6 -0
  247. package/corpus/templates/design/changelog/2026-07-06-undo-and-redo-no-longer-flash-the-screen-changes-now-apply-i.md +6 -0
  248. package/corpus/templates/design/changelog/2026-07-06-zoom-presets-like-zoom-to-50-now-stay-on-the-focused-screen-.md +6 -0
  249. package/corpus/templates/design/server/lib/import-design-files.ts +11 -2
  250. package/corpus/templates/design/server/source-workspace.ts +139 -59
  251. package/corpus/templates/design/shared/board-file.ts +11 -2
  252. package/corpus/templates/design/shared/breakpoint-media.ts +543 -0
  253. package/corpus/templates/design/shared/canvas-math.ts +354 -35
  254. package/corpus/templates/design/shared/code-layer.ts +277 -8
  255. package/corpus/templates/design/shared/design-state.ts +11 -4
  256. package/corpus/templates/design/shared/interaction-states.ts +548 -0
  257. package/corpus/templates/design/shared/motion-compiler.ts +186 -23
  258. package/corpus/templates/design/shared/motion-easing.ts +294 -0
  259. package/corpus/templates/design/shared/motion-timeline.ts +400 -34
  260. package/corpus/templates/design/shared/prompt-title.ts +95 -0
  261. package/corpus/templates/design/shared/responsive-classes.ts +448 -10
  262. package/corpus/templates/design/shared/screen-annotation.ts +46 -0
  263. package/corpus/templates/design/shared/shader-fills.ts +1009 -0
  264. package/corpus/templates/design/shared/shader-presets.ts +852 -4
  265. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +15 -2
  266. package/corpus/templates/slides/app/components/editor/ImportButton.tsx +10 -1
  267. package/corpus/templates/slides/app/lib/upload-response.ts +71 -0
  268. package/dist/client/AgentPanel.js +1 -1
  269. package/dist/client/AgentPanel.js.map +1 -1
  270. package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts.map +1 -1
  271. package/dist/client/rich-markdown-editor/useCollabReconcile.js +11 -6
  272. package/dist/client/rich-markdown-editor/useCollabReconcile.js.map +1 -1
  273. package/dist/client/use-action.d.ts +3 -0
  274. package/dist/client/use-action.d.ts.map +1 -1
  275. package/dist/client/use-action.js +34 -3
  276. package/dist/client/use-action.js.map +1 -1
  277. package/dist/client/use-db-sync.d.ts +4 -0
  278. package/dist/client/use-db-sync.d.ts.map +1 -1
  279. package/dist/client/use-db-sync.js +37 -18
  280. package/dist/client/use-db-sync.js.map +1 -1
  281. package/dist/collab/routes.d.ts +1 -1
  282. package/dist/collab/struct-routes.d.ts +1 -1
  283. package/dist/db/create-get-db.d.ts +25 -0
  284. package/dist/db/create-get-db.d.ts.map +1 -1
  285. package/dist/db/create-get-db.js +25 -2
  286. package/dist/db/create-get-db.js.map +1 -1
  287. package/dist/observability/routes.d.ts +3 -3
  288. package/dist/secrets/routes.d.ts +9 -9
  289. package/dist/server/framework-request-handler.d.ts.map +1 -1
  290. package/dist/server/framework-request-handler.js +37 -1
  291. package/dist/server/framework-request-handler.js.map +1 -1
  292. package/package.json +1 -1
  293. package/corpus/templates/design/app/components/design/inspector/InspectorAiActions.tsx +0 -153
  294. package/corpus/templates/design/app/hooks/useAgentEditRequest.ts +0 -133
  295. package/corpus/templates/design/app/pages/DesignEditor.tsx +0 -22924
@@ -87,58 +87,58 @@ cd templates/content && pnpm action <name> [args]
87
87
 
88
88
  ### Document Operations
89
89
 
90
- | Action | Args | Purpose |
91
- | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
92
- | `list-documents` | `[--format json]` | List document metadata/tree; no full bodies |
93
- | `export-content-source` | `[--format json]` | Export editable docs as `content/*.mdx` source files |
94
- | `import-content-source` | `--files <json> [--dryRun true\|false]` | Import `.md`/`.mdx` source files into editable docs |
95
- | `list-builder-docs` | `[--model docs-content\|blog-article] [--limit <n>]` | List Builder docs/blog entries available for `.builder.mdx` pull |
96
- | `pull-builder-doc` | `--model <model> --entryId <builder-entry-id> [--dryRun true\|false]` | Pull one Builder entry into Content and return `.builder.mdx` plus `content/builder/.raw` sidecar files |
97
- | `check-builder-doc` | `--files <json> [--path <file.builder.mdx>]` or `--documentId <id>` | Validate Builder MDX round-trip, sidecar hashes, and remote conflict status before push |
98
- | `push-builder-doc` | `--files <json> [--path <file.builder.mdx>] [--dryRun true\|false]` | Guarded Builder autosave PATCH for the safe Builder test model; never publishes |
99
- | `navigate` | `--path <path>` or `--documentId <id>` or `--databaseId <id>` | Open a route, document page, or database page in the UI |
100
- | `search-documents` | `--query <text> [--format json]` | Search by title/content and return snippets |
101
- | `get-document` | `--id <id> [--format json]` | Get a single document with content |
102
- | `pull-document` | `--id <id> [--format markdown\|text]` | Collab-aware "ingest the final" read |
103
- | `create-document` | `--title <text> [--content] [--parentId] [--icon]` | Create a new document |
104
- | `edit-document` | `--id <id> --find <text> --replace <text>` | Surgical text edit (preferred for modifications) |
105
- | `edit-document` | `--id <id> --edits <json>` | Batch surgical text edits |
106
- | `update-document` | `--id <id> [--title] [--content] [--icon]` | Full rewrite of document fields |
107
- | `share-local-file-document` | `--id <local-file-document-id>` | Create or refresh a DB-backed shareable copy of a local file document |
108
- | `remove-local-file-source` | `[--sourceRootPath <path>]` | Unlink local-file sources from Content without deleting local Markdown/MDX files |
109
- | `list-local-component-files` | | List registered local MDX component source files |
110
- | `write-local-component-file` | `--workspaceId <id> --path <relative-component-path> --content <source>` | Create or update a file in a registered local `components/` folder |
111
- | `create-content-database` | `[--documentId <id>] [--parentId <id>] [--title <text>]` | Create a database page or convert an existing page into a database |
112
- | `create-inline-content-database` | `--hostDocumentId <id> [--title <text>]` | Create a database owned by an inline database block in the host document |
113
- | `get-content-database` | `--databaseId <id>` or `--documentId <id>` | Get a database table with property schema and item pages |
114
- | `list-trashed-content-databases` | | List soft-deleted databases visible in the sidebar Trash surface |
115
- | `restore-content-database` | `--databaseId <id>` | Restore a soft-deleted database from the sidebar Trash surface |
116
- | `get-content-database-source` | `--databaseId <id>` or `--documentId <id>` | Inspect local/no-source or source-backed status, mappings, row identity, freshness, and change sets |
117
- | `attach-content-database-source` | `--databaseId <id>` or `--documentId <id> [--sourceType mock\|builder-cms] [--sourceName] [--sourceTable] [--relationshipMode items\|details] [--join <json>]` | Attach a source binding; use `items` to add more rows and `details` to match a source onto existing rows |
118
- | `change-content-database-source-role` | `--databaseId <id>` or `--documentId <id> --sourceId <id> --relationshipMode items\|details [--join <json>]` | Change an attached source between adding rows and adding matched detail columns without removing the source |
119
- | `refresh-content-database-source` | `--databaseId <id>` or `--documentId <id>` | Refresh the read-only source status envelope; Builder CMS reads live entries only when configured |
120
- | `process-builder-body-hydration` | `--sourceId <id> [--documentId <id>] [--limit <n>]` | Hydrate queued Builder article bodies into readable Content markdown with preserved source-component markers |
121
- | `set-content-database-source-write-mode` | `--databaseId <id>` or `--documentId <id> --liveWritesEnabled true\|false [--allowedWriteModes <json>]` | Enable/disable per-source Builder live writes; enabling is allowed only for `agent-native-blog-article-test` with explicit modes |
122
- | `stage-builder-revision` | `--databaseId <id>` or `--documentId <id>` | Stage pending local Builder CMS changes as a local-only save-revision record; never calls Builder |
123
- | `review-content-database-source-change-set` | `--databaseId <id>` or `--documentId <id> --changeSetId <id> --decision approve\|reject [--note]` | Approve or reject a local source change-set review record without provider writes |
124
- | `prepare-builder-source-execution` | `--databaseId <id>` or `--documentId <id> --changeSetId <id> [--pushModeConfirmation autosave\|draft\|publish]` | Prepare a dry-run Builder execution gate for approved field/body changes with request semantics/idempotency key; never calls Builder |
125
- | `validate-builder-source-execution` | `--databaseId <id>` or `--documentId <id> --changeSetId <id> [--idempotencyKey <key>]` | Validate/replay a prepared Builder execution gate locally as a dry run; never calls Builder |
126
- | `execute-builder-source-execution` | `--databaseId <id>` or `--documentId <id> --changeSetId <id> [--idempotencyKey <key>] [--pushModeConfirmation autosave\|draft\|publish]` | Execute a guarded live Builder write only when approved, validated, enabled, idempotent, and targeting `agent-native-blog-article-test` |
127
- | `add-database-item` | `--databaseId <id> [--title <text>] [--propertyValues <json>]` | Add a page row to a database, optionally seeding property values |
128
- | `duplicate-database-item` | `--itemId <id>` or `--documentId <id> [--title <text>]` | Duplicate exactly one database row page and its stored property values; for two or more rows, use `duplicate-database-items` once |
129
- | `duplicate-database-items` | `--databaseId <id>` or `--documentId <databaseDocumentId> --itemIds <json-array>` or `--documentIds <json-array>` | Preferred multi-row duplicate action; duplicate multiple database row pages atomically and return ordered duplicate item/document IDs |
130
- | `delete-database-items` | `--databaseId <id>` or `--documentId <databaseDocumentId> --itemIds <json-array>` or `--documentIds <json-array>` | Preferred multi-row delete action; delete multiple database row pages atomically while preserving `delete-document` admin semantics |
131
- | `move-database-item` | `--itemId <id>` or `--documentId <id> --position <number>` | Move a database row page to a new zero-based table position |
132
- | `update-content-database-view` | `--databaseId <id> --viewConfig <json>` | Persist database views, sorts, filters, hidden properties, and view settings |
133
- | `list-document-properties` | `--documentId <id> [--format json]` | List Notion-style property definitions and values for a document |
134
- | `configure-document-property` | `--documentId <id> [--id <propertyId>] --name <name> --type <type> [--visibility always_show\|hide_when_empty\|always_hide]` | Create or update a property definition |
135
- | `duplicate-document-property` | `--documentId <id> --propertyId <propertyId>` | Duplicate a property definition and its stored values |
136
- | `delete-document-property` | `--documentId <id> --propertyId <propertyId>` | Delete a property definition and its stored values |
137
- | `set-document-property` | `--documentId <id> --propertyId <propertyId> --value <json>` | Set a document property value (for a `blocks` field, the value is its markdown content) |
138
- | `reorder-document-property` | `--documentId <id> --propertyId <propertyId> --targetPropertyId <id> [--position before\|after]` | Reorder a property definition within its database (used to reorder Blocks fields on the page) |
139
- | `set-document-discoverability` | `--id <id> --hideFromSearch true\|false [--includeChildren true\|false]` | Hide/show an org-accessible document in Organization/search while keeping link access |
140
- | `move-document` | `--id <id> [--parentId] [--position]` | Move or reorder a document in the page tree |
141
- | `delete-document` | `--id <id>` | Delete with recursive children |
90
+ | Action | Args | Purpose |
91
+ | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
92
+ | `list-documents` | `[--format json]` | List document metadata/tree; no full bodies |
93
+ | `export-content-source` | `[--format json]` | Export editable docs as `content/*.mdx` source files |
94
+ | `import-content-source` | `--files <json> [--dryRun true\|false]` | Import `.md`/`.mdx` source files into editable docs |
95
+ | `list-builder-docs` | `[--model docs-content\|blog-article] [--limit <n>]` | List Builder docs/blog entries available for `.builder.mdx` pull |
96
+ | `pull-builder-doc` | `--model <model> --entryId <builder-entry-id> [--dryRun true\|false]` | Pull one Builder entry into Content and return `.builder.mdx` plus `content/builder/.raw` sidecar files |
97
+ | `check-builder-doc` | `--files <json> [--path <file.builder.mdx>]` or `--documentId <id>` | Validate Builder MDX round-trip, sidecar hashes, and remote conflict status before push |
98
+ | `push-builder-doc` | `--files <json> [--path <file.builder.mdx>] [--dryRun true\|false]` | Guarded Builder autosave PATCH for the safe Builder test model; never publishes |
99
+ | `navigate` | `--path <path>` or `--documentId <id>` or `--databaseId <id>` | Open a route, document page, or database page in the UI |
100
+ | `search-documents` | `--query <text> [--format json]` | Search by title/content and return snippets |
101
+ | `get-document` | `--id <id> [--format json]` | Get a single document with content |
102
+ | `pull-document` | `--id <id> [--format markdown\|text]` | Collab-aware "ingest the final" read |
103
+ | `create-document` | `--title <text> [--content] [--parentId] [--icon]` | Create a new document |
104
+ | `edit-document` | `--id <id> --find <text> --replace <text>` | Surgical text edit (preferred for modifications) |
105
+ | `edit-document` | `--id <id> --edits <json>` | Batch surgical text edits |
106
+ | `update-document` | `--id <id> [--title] [--content] [--icon]` | Full rewrite of document fields |
107
+ | `share-local-file-document` | `--id <local-file-document-id>` | Create or refresh a DB-backed shareable copy of a local file document |
108
+ | `remove-local-file-source` | `[--sourceRootPath <path>]` | Unlink local-file sources from Content without deleting local Markdown/MDX files |
109
+ | `list-local-component-files` | | List registered local MDX component source files |
110
+ | `write-local-component-file` | `--workspaceId <id> --path <relative-component-path> --content <source>` | Create or update a file in a registered local `components/` folder |
111
+ | `create-content-database` | `[--documentId <id>] [--parentId <id>] [--title <text>]` | Create a database page or convert an existing page into a database |
112
+ | `create-inline-content-database` | `--hostDocumentId <id> [--title <text>]` | Create a database owned by an inline database block in the host document |
113
+ | `get-content-database` | `--databaseId <id>` or `--documentId <id>` | Get a database table with property schema and item pages |
114
+ | `list-trashed-content-databases` | | List soft-deleted databases visible in the sidebar Trash surface |
115
+ | `restore-content-database` | `--databaseId <id>` | Restore a soft-deleted database from the sidebar Trash surface |
116
+ | `get-content-database-source` | `--databaseId <id>` or `--documentId <id>` | Inspect local/no-source or source-backed status, mappings, row identity, freshness, and change sets |
117
+ | `attach-content-database-source` | `--databaseId <id>` or `--documentId <id> [--sourceType mock\|builder-cms] [--sourceName] [--sourceTable] [--relationshipMode items\|details] [--join <json>]` | Attach a source binding; use `items` to add more rows and `details` to match a source onto existing rows |
118
+ | `change-content-database-source-role` | `--databaseId <id>` or `--documentId <id> --sourceId <id> --relationshipMode items\|details [--join <json>]` | Change an attached source between adding rows and adding matched detail columns without removing the source |
119
+ | `refresh-content-database-source` | `--databaseId <id>` or `--documentId <id>` | Refresh the read-only source status envelope; large Builder CMS sources may return a partial fetch, and another refresh continues loading remaining rows |
120
+ | `process-builder-body-hydration` | `--sourceId <id> [--documentId <id>] [--limit <n>]` | Hydrate queued Builder article bodies into readable Content markdown with preserved source-component markers |
121
+ | `set-content-database-source-write-mode` | `--databaseId <id>` or `--documentId <id> --liveWritesEnabled true\|false [--allowedWriteModes <json>]` | Enable/disable per-source Builder live writes; enabling is allowed only for `agent-native-blog-article-test` with explicit modes |
122
+ | `stage-builder-revision` | `--databaseId <id>` or `--documentId <id>` | Stage pending local Builder CMS changes as a local-only save-revision record; never calls Builder |
123
+ | `review-content-database-source-change-set` | `--databaseId <id>` or `--documentId <id> --changeSetId <id> --decision approve\|reject [--note]` | Approve or reject a local source change-set review record without provider writes |
124
+ | `prepare-builder-source-execution` | `--databaseId <id>` or `--documentId <id> --changeSetId <id> [--pushModeConfirmation autosave\|draft\|publish]` | Prepare a dry-run Builder execution gate for approved field/body changes with request semantics/idempotency key; never calls Builder |
125
+ | `validate-builder-source-execution` | `--databaseId <id>` or `--documentId <id> --changeSetId <id> [--idempotencyKey <key>]` | Validate/replay a prepared Builder execution gate locally as a dry run; never calls Builder |
126
+ | `execute-builder-source-execution` | `--databaseId <id>` or `--documentId <id> --changeSetId <id> [--idempotencyKey <key>] [--pushModeConfirmation autosave\|draft\|publish]` | Execute a guarded live Builder write only when approved, validated, enabled, idempotent, and targeting `agent-native-blog-article-test` |
127
+ | `add-database-item` | `--databaseId <id> [--title <text>] [--propertyValues <json>]` | Add a page row to a database, optionally seeding property values |
128
+ | `duplicate-database-item` | `--itemId <id>` or `--documentId <id> [--title <text>]` | Duplicate exactly one database row page and its stored property values; for two or more rows, use `duplicate-database-items` once |
129
+ | `duplicate-database-items` | `--databaseId <id>` or `--documentId <databaseDocumentId> --itemIds <json-array>` or `--documentIds <json-array>` | Preferred multi-row duplicate action; duplicate multiple database row pages atomically and return ordered duplicate item/document IDs |
130
+ | `delete-database-items` | `--databaseId <id>` or `--documentId <databaseDocumentId> --itemIds <json-array>` or `--documentIds <json-array>` | Preferred multi-row delete action; delete multiple database row pages atomically while preserving `delete-document` admin semantics |
131
+ | `move-database-item` | `--itemId <id>` or `--documentId <id> --position <number>` | Move a database row page to a new zero-based table position |
132
+ | `update-content-database-view` | `--databaseId <id> --viewConfig <json>` | Persist database views, sorts, filters, hidden properties, and view settings |
133
+ | `list-document-properties` | `--documentId <id> [--format json]` | List Notion-style property definitions and values for a document |
134
+ | `configure-document-property` | `--documentId <id> [--id <propertyId>] --name <name> --type <type> [--visibility always_show\|hide_when_empty\|always_hide]` | Create or update a property definition |
135
+ | `duplicate-document-property` | `--documentId <id> --propertyId <propertyId>` | Duplicate a property definition and its stored values |
136
+ | `delete-document-property` | `--documentId <id> --propertyId <propertyId>` | Delete a property definition and its stored values |
137
+ | `set-document-property` | `--documentId <id> --propertyId <propertyId> --value <json>` | Set a document property value (for a `blocks` field, the value is its markdown content) |
138
+ | `reorder-document-property` | `--documentId <id> --propertyId <propertyId> --targetPropertyId <id> [--position before\|after]` | Reorder a property definition within its database (used to reorder Blocks fields on the page) |
139
+ | `set-document-discoverability` | `--id <id> --hideFromSearch true\|false [--includeChildren true\|false]` | Hide/show an org-accessible document in Organization/search while keeping link access |
140
+ | `move-document` | `--id <id> [--parentId] [--position]` | Move or reorder a document in the page tree |
141
+ | `delete-document` | `--id <id>` | Delete with recursive children |
142
142
 
143
143
  Database views follow Notion-style tab labels. When creating or duplicating
144
144
  views in `viewConfig`, use unique default names (`Table 2`, `SEO copy 2`, etc.)
@@ -22,6 +22,18 @@ export interface BuilderCmsReadResult {
22
22
  entries: BuilderCmsSourceEntry[];
23
23
  fetchedAt: string;
24
24
  message: string | null;
25
+ progress: BuilderCmsReadProgress;
26
+ }
27
+
28
+ export interface BuilderCmsReadProgress {
29
+ requestedLimit: number;
30
+ pageSize: number;
31
+ startOffset: number;
32
+ nextOffset: number;
33
+ fetchedEntryCount: number;
34
+ hasMore: boolean;
35
+ partial: boolean;
36
+ readMode: "builder-api" | "mcp" | "none";
25
37
  }
26
38
 
27
39
  export interface BuilderCmsEntryLiveState {
@@ -385,6 +397,8 @@ async function initializeBuilderMcp(args: {
385
397
  async function readBuilderCmsContentEntriesViaMcp(args: {
386
398
  model: string;
387
399
  limit?: number;
400
+ maxPages?: number;
401
+ offset?: number;
388
402
  fetchImpl: FetchLike;
389
403
  privateKey: string;
390
404
  }): Promise<BuilderCmsReadResult> {
@@ -397,14 +411,22 @@ async function readBuilderCmsContentEntriesViaMcp(args: {
397
411
  });
398
412
 
399
413
  const limit = readLimit(args.limit);
414
+ const startOffset =
415
+ typeof args.offset === "number" && Number.isFinite(args.offset)
416
+ ? Math.max(0, Math.floor(args.offset))
417
+ : 0;
400
418
  const contentEntries: BuilderCmsSourceEntry[] = [];
401
419
  const seenContentIds = new Set<string>();
420
+ let pagesRead = 0;
421
+ let hasMore = false;
402
422
  for (
403
- let offset = 0;
404
- contentEntries.length < limit;
423
+ let offset = startOffset;
424
+ startOffset + contentEntries.length < limit;
405
425
  offset += BUILDER_CMS_PAGE_SIZE
406
426
  ) {
407
- const pageLimit = readPageLimit(limit - contentEntries.length);
427
+ const pageLimit = readPageLimit(
428
+ limit - startOffset - contentEntries.length,
429
+ );
408
430
  const contentResult = await postBuilderMcp({
409
431
  endpoint,
410
432
  privateKey: args.privateKey,
@@ -436,7 +458,13 @@ async function readBuilderCmsContentEntriesViaMcp(args: {
436
458
  seenContentIds,
437
459
  pageEntries,
438
460
  );
439
- if (pageEntries.length < pageLimit || appended === 0) break;
461
+ pagesRead += 1;
462
+ hasMore =
463
+ pageEntries.length >= pageLimit &&
464
+ appended > 0 &&
465
+ contentEntries.length < limit;
466
+ if (args.maxPages && pagesRead >= args.maxPages) break;
467
+ if (!hasMore) break;
440
468
  }
441
469
  if (contentEntries.length > 0) {
442
470
  return {
@@ -444,6 +472,16 @@ async function readBuilderCmsContentEntriesViaMcp(args: {
444
472
  entries: contentEntries,
445
473
  fetchedAt,
446
474
  message: null,
475
+ progress: {
476
+ requestedLimit: limit,
477
+ pageSize: BUILDER_CMS_PAGE_SIZE,
478
+ startOffset,
479
+ nextOffset: startOffset + contentEntries.length,
480
+ fetchedEntryCount: startOffset + contentEntries.length,
481
+ hasMore,
482
+ partial: hasMore && Boolean(args.maxPages),
483
+ readMode: "mcp",
484
+ },
447
485
  };
448
486
  }
449
487
 
@@ -458,6 +496,16 @@ async function readBuilderCmsContentEntriesViaMcp(args: {
458
496
  entries: [],
459
497
  fetchedAt,
460
498
  message: null,
499
+ progress: {
500
+ requestedLimit: limit,
501
+ pageSize: BUILDER_CMS_PAGE_SIZE,
502
+ startOffset,
503
+ nextOffset: startOffset,
504
+ fetchedEntryCount: 0,
505
+ hasMore: false,
506
+ partial: false,
507
+ readMode: "mcp",
508
+ },
461
509
  };
462
510
  }
463
511
 
@@ -522,12 +570,24 @@ async function readBuilderCmsContentEntriesViaMcp(args: {
522
570
  entries: hydratedEntries,
523
571
  fetchedAt,
524
572
  message: null,
573
+ progress: {
574
+ requestedLimit: limit,
575
+ pageSize: BUILDER_CMS_PAGE_SIZE,
576
+ startOffset,
577
+ nextOffset: startOffset + hydratedEntries.length,
578
+ fetchedEntryCount: startOffset + hydratedEntries.length,
579
+ hasMore: false,
580
+ partial: false,
581
+ readMode: "mcp",
582
+ },
525
583
  };
526
584
  }
527
585
 
528
586
  async function readBuilderCmsContentEntriesViaContentApi(args: {
529
587
  model: string;
530
588
  limit?: number;
589
+ maxPages?: number;
590
+ offset?: number;
531
591
  fetchImpl: FetchLike;
532
592
  publicKey: string;
533
593
  }): Promise<BuilderCmsReadResult> {
@@ -544,15 +604,21 @@ async function readBuilderCmsContentEntriesViaContentApi(args: {
544
604
  url.searchParams.set("noCache", "true");
545
605
 
546
606
  const limit = readLimit(args.limit);
607
+ const startOffset =
608
+ typeof args.offset === "number" && Number.isFinite(args.offset)
609
+ ? Math.max(0, Math.floor(args.offset))
610
+ : 0;
547
611
  const entries: BuilderCmsSourceEntry[] = [];
548
612
  const seenIds = new Set<string>();
613
+ let pagesRead = 0;
614
+ let hasMore = false;
549
615
  for (
550
- let offset = 0;
551
- entries.length < limit;
616
+ let offset = startOffset;
617
+ startOffset + entries.length < limit;
552
618
  offset += BUILDER_CMS_PAGE_SIZE
553
619
  ) {
554
620
  const pageUrl = new URL(url);
555
- const pageLimit = readPageLimit(limit - entries.length);
621
+ const pageLimit = readPageLimit(limit - startOffset - entries.length);
556
622
  pageUrl.searchParams.set("limit", String(pageLimit));
557
623
  pageUrl.searchParams.set("offset", String(offset));
558
624
 
@@ -571,6 +637,16 @@ async function readBuilderCmsContentEntriesViaContentApi(args: {
571
637
  error instanceof Error
572
638
  ? `Builder CMS read failed: ${error.message}`
573
639
  : "Builder CMS read failed.",
640
+ progress: {
641
+ requestedLimit: limit,
642
+ pageSize: BUILDER_CMS_PAGE_SIZE,
643
+ startOffset,
644
+ nextOffset: startOffset + entries.length,
645
+ fetchedEntryCount: startOffset + entries.length,
646
+ hasMore,
647
+ partial: Boolean(args.maxPages) && hasMore,
648
+ readMode: "builder-api",
649
+ },
574
650
  };
575
651
  }
576
652
 
@@ -580,6 +656,16 @@ async function readBuilderCmsContentEntriesViaContentApi(args: {
580
656
  entries: [],
581
657
  fetchedAt,
582
658
  message: `Builder CMS read failed with HTTP ${response.status}.`,
659
+ progress: {
660
+ requestedLimit: limit,
661
+ pageSize: BUILDER_CMS_PAGE_SIZE,
662
+ startOffset,
663
+ nextOffset: startOffset + entries.length,
664
+ fetchedEntryCount: startOffset + entries.length,
665
+ hasMore,
666
+ partial: Boolean(args.maxPages) && hasMore,
667
+ readMode: "builder-api",
668
+ },
583
669
  };
584
670
  }
585
671
 
@@ -588,7 +674,11 @@ async function readBuilderCmsContentEntriesViaContentApi(args: {
588
674
  .map((entry) => normalizeBuilderCmsApiEntry(entry, args.model))
589
675
  .filter((entry): entry is BuilderCmsSourceEntry => Boolean(entry));
590
676
  const appended = appendUniqueBuilderEntries(entries, seenIds, pageEntries);
591
- if (pageEntries.length < pageLimit || appended === 0) break;
677
+ pagesRead += 1;
678
+ hasMore =
679
+ pageEntries.length >= pageLimit && appended > 0 && entries.length < limit;
680
+ if (args.maxPages && pagesRead >= args.maxPages) break;
681
+ if (!hasMore) break;
592
682
  }
593
683
 
594
684
  return {
@@ -596,6 +686,16 @@ async function readBuilderCmsContentEntriesViaContentApi(args: {
596
686
  entries,
597
687
  fetchedAt,
598
688
  message: null,
689
+ progress: {
690
+ requestedLimit: limit,
691
+ pageSize: BUILDER_CMS_PAGE_SIZE,
692
+ startOffset,
693
+ nextOffset: startOffset + entries.length,
694
+ fetchedEntryCount: startOffset + entries.length,
695
+ hasMore,
696
+ partial: hasMore && Boolean(args.maxPages),
697
+ readMode: "builder-api",
698
+ },
599
699
  };
600
700
  }
601
701
 
@@ -644,6 +744,50 @@ export async function readBuilderCmsEntryLiveState(args: {
644
744
  return liveStateFromBuilderEntry(json);
645
745
  }
646
746
 
747
+ export async function readBuilderCmsContentEntry(args: {
748
+ model: string;
749
+ entryId: string;
750
+ fetchImpl?: FetchLike;
751
+ }): Promise<BuilderCmsSourceEntry | null> {
752
+ const publicKey = await resolveBuilderCredential("BUILDER_PUBLIC_KEY");
753
+ if (!publicKey) {
754
+ throw new Error(
755
+ "Builder CMS entry read skipped because BUILDER_PUBLIC_KEY is not configured.",
756
+ );
757
+ }
758
+
759
+ const url = new URL(
760
+ `/api/v3/content/${encodeURIComponent(args.model)}/${encodeURIComponent(
761
+ args.entryId,
762
+ )}`,
763
+ builderContentApiHost(),
764
+ );
765
+ url.searchParams.set("apiKey", publicKey);
766
+ url.searchParams.set("includeUnpublished", "true");
767
+ url.searchParams.set("enrich", "true");
768
+ url.searchParams.set("noCache", "true");
769
+ url.searchParams.set("cachebust", String(Date.now()));
770
+ url.searchParams.set("fields", BUILDER_CMS_ENTRY_FIELDS);
771
+
772
+ const response = await fetchBuilderContentPage({
773
+ fetchImpl: args.fetchImpl ?? fetch,
774
+ url,
775
+ });
776
+ if (response.status === 404) return null;
777
+ if (!response.ok) {
778
+ throw new Error(
779
+ `Builder CMS entry read failed with HTTP ${response.status}.`,
780
+ );
781
+ }
782
+
783
+ const json = (await response.json()) as unknown;
784
+ const rawEntry = Array.isArray(json)
785
+ ? json[0]
786
+ : (entryArrayFromResponse(json)[0] ?? json);
787
+ const entry = normalizeBuilderCmsApiEntry(rawEntry, args.model);
788
+ return entry?.id === args.entryId ? entry : null;
789
+ }
790
+
647
791
  export async function listBuilderCmsModels(
648
792
  args: {
649
793
  fetchImpl?: FetchLike;
@@ -725,6 +869,8 @@ export async function readBuilderCmsModelFields(args: {
725
869
  export async function readBuilderCmsContentEntries(args: {
726
870
  model: string;
727
871
  limit?: number;
872
+ maxPages?: number;
873
+ offset?: number;
728
874
  fetchImpl?: FetchLike;
729
875
  }): Promise<BuilderCmsReadResult> {
730
876
  const fetchedAt = new Date().toISOString();
@@ -735,6 +881,8 @@ export async function readBuilderCmsContentEntries(args: {
735
881
  const contentApiRead = await readBuilderCmsContentEntriesViaContentApi({
736
882
  model: args.model,
737
883
  limit: args.limit,
884
+ maxPages: args.maxPages,
885
+ offset: args.offset,
738
886
  fetchImpl,
739
887
  publicKey,
740
888
  });
@@ -749,6 +897,8 @@ export async function readBuilderCmsContentEntries(args: {
749
897
  return await readBuilderCmsContentEntriesViaMcp({
750
898
  model: args.model,
751
899
  limit: args.limit,
900
+ maxPages: args.maxPages,
901
+ offset: args.offset,
752
902
  fetchImpl,
753
903
  privateKey,
754
904
  });
@@ -761,6 +911,16 @@ export async function readBuilderCmsContentEntries(args: {
761
911
  error instanceof Error
762
912
  ? error.message
763
913
  : "Builder CMS MCP read failed.",
914
+ progress: {
915
+ requestedLimit: readLimit(args.limit),
916
+ pageSize: BUILDER_CMS_PAGE_SIZE,
917
+ startOffset: 0,
918
+ nextOffset: 0,
919
+ fetchedEntryCount: 0,
920
+ hasMore: false,
921
+ partial: false,
922
+ readMode: "mcp",
923
+ },
764
924
  };
765
925
  }
766
926
  }
@@ -772,6 +932,16 @@ export async function readBuilderCmsContentEntries(args: {
772
932
  fetchedAt,
773
933
  message:
774
934
  "Builder CMS read skipped because BUILDER_PUBLIC_KEY is not configured.",
935
+ progress: {
936
+ requestedLimit: readLimit(args.limit),
937
+ pageSize: BUILDER_CMS_PAGE_SIZE,
938
+ startOffset: 0,
939
+ nextOffset: 0,
940
+ fetchedEntryCount: 0,
941
+ hasMore: false,
942
+ partial: false,
943
+ readMode: "none",
944
+ },
775
945
  };
776
946
  }
777
947
 
@@ -780,5 +950,15 @@ export async function readBuilderCmsContentEntries(args: {
780
950
  entries: [],
781
951
  fetchedAt,
782
952
  message: "Builder CMS read returned no entries.",
953
+ progress: {
954
+ requestedLimit: readLimit(args.limit),
955
+ pageSize: BUILDER_CMS_PAGE_SIZE,
956
+ startOffset: 0,
957
+ nextOffset: 0,
958
+ fetchedEntryCount: 0,
959
+ hasMore: false,
960
+ partial: false,
961
+ readMode: "none",
962
+ },
783
963
  };
784
964
  }
@@ -40,6 +40,23 @@ import { flushOpenDocumentEditorToSql } from "./_document-flush.js";
40
40
 
41
41
  type FetchLike = typeof fetch;
42
42
 
43
+ function builderDocsReadProgress(args: {
44
+ limit: number;
45
+ count: number;
46
+ readMode: "builder-api" | "none";
47
+ }): BuilderCmsReadResult["progress"] {
48
+ return {
49
+ requestedLimit: args.limit,
50
+ pageSize: args.limit,
51
+ startOffset: 0,
52
+ nextOffset: args.count,
53
+ fetchedEntryCount: args.count,
54
+ hasMore: false,
55
+ partial: false,
56
+ readMode: args.readMode,
57
+ };
58
+ }
59
+
43
60
  export interface BuilderDocsFilesInput {
44
61
  path?: string | null;
45
62
  files?: Record<string, string> | null;
@@ -263,6 +280,11 @@ async function readBuilderDocsPublishedEntries(args: {
263
280
  fetchedAt,
264
281
  message:
265
282
  "Builder docs list skipped because BUILDER_PUBLIC_KEY is not configured.",
283
+ progress: builderDocsReadProgress({
284
+ limit: args.limit,
285
+ count: 0,
286
+ readMode: "none",
287
+ }),
266
288
  };
267
289
  }
268
290
 
@@ -289,6 +311,11 @@ async function readBuilderDocsPublishedEntries(args: {
289
311
  error instanceof Error
290
312
  ? `Builder docs list failed: ${error.message}`
291
313
  : "Builder docs list failed.",
314
+ progress: builderDocsReadProgress({
315
+ limit: args.limit,
316
+ count: 0,
317
+ readMode: "builder-api",
318
+ }),
292
319
  };
293
320
  }
294
321
 
@@ -298,17 +325,28 @@ async function readBuilderDocsPublishedEntries(args: {
298
325
  entries: [],
299
326
  fetchedAt,
300
327
  message: `Builder docs list failed with HTTP ${response.status}.`,
328
+ progress: builderDocsReadProgress({
329
+ limit: args.limit,
330
+ count: 0,
331
+ readMode: "builder-api",
332
+ }),
301
333
  };
302
334
  }
303
335
 
304
336
  const json = (await response.json()) as unknown;
337
+ const entries = entryArrayFromResponse(json)
338
+ .map((entry) => normalizeBuilderCmsApiEntry(entry, args.model))
339
+ .filter((entry): entry is BuilderCmsSourceEntry => Boolean(entry));
305
340
  return {
306
341
  state: "live",
307
- entries: entryArrayFromResponse(json)
308
- .map((entry) => normalizeBuilderCmsApiEntry(entry, args.model))
309
- .filter((entry): entry is BuilderCmsSourceEntry => Boolean(entry)),
342
+ entries,
310
343
  fetchedAt,
311
344
  message: null,
345
+ progress: builderDocsReadProgress({
346
+ limit: args.limit,
347
+ count: entries.length,
348
+ readMode: "builder-api",
349
+ }),
312
350
  };
313
351
  }
314
352