@agent-native/core 0.83.0 → 0.84.1

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 (508) hide show
  1. package/README.md +2 -2
  2. package/corpus/README.md +1 -1
  3. package/corpus/core/CHANGELOG.md +34 -0
  4. package/corpus/core/README.md +2 -2
  5. package/corpus/core/docs/content/cloneable-saas.mdx +2 -2
  6. package/corpus/core/docs/content/evals.mdx +34 -12
  7. package/corpus/core/docs/content/faq.mdx +1 -1
  8. package/corpus/core/docs/content/locales/ar-SA/cloneable-saas.mdx +2 -2
  9. package/corpus/core/docs/content/locales/ar-SA/evals.mdx +7 -0
  10. package/corpus/core/docs/content/locales/ar-SA/faq.mdx +1 -1
  11. package/corpus/core/docs/content/locales/ar-SA/template-chat.mdx +1 -1
  12. package/corpus/core/docs/content/locales/de-DE/cloneable-saas.mdx +2 -2
  13. package/corpus/core/docs/content/locales/de-DE/evals.mdx +8 -0
  14. package/corpus/core/docs/content/locales/de-DE/faq.mdx +1 -1
  15. package/corpus/core/docs/content/locales/de-DE/template-chat.mdx +1 -1
  16. package/corpus/core/docs/content/locales/es-ES/cloneable-saas.mdx +2 -2
  17. package/corpus/core/docs/content/locales/es-ES/evals.mdx +8 -0
  18. package/corpus/core/docs/content/locales/es-ES/faq.mdx +1 -1
  19. package/corpus/core/docs/content/locales/es-ES/template-chat.mdx +1 -1
  20. package/corpus/core/docs/content/locales/fr-FR/cloneable-saas.mdx +2 -2
  21. package/corpus/core/docs/content/locales/fr-FR/evals.mdx +8 -0
  22. package/corpus/core/docs/content/locales/fr-FR/faq.mdx +1 -1
  23. package/corpus/core/docs/content/locales/fr-FR/template-chat.mdx +1 -1
  24. package/corpus/core/docs/content/locales/hi-IN/cloneable-saas.mdx +2 -2
  25. package/corpus/core/docs/content/locales/hi-IN/evals.mdx +8 -0
  26. package/corpus/core/docs/content/locales/hi-IN/faq.mdx +1 -1
  27. package/corpus/core/docs/content/locales/hi-IN/template-chat.mdx +1 -1
  28. package/corpus/core/docs/content/locales/ja-JP/cloneable-saas.mdx +2 -2
  29. package/corpus/core/docs/content/locales/ja-JP/evals.mdx +7 -0
  30. package/corpus/core/docs/content/locales/ja-JP/faq.mdx +1 -1
  31. package/corpus/core/docs/content/locales/ja-JP/template-chat.mdx +1 -1
  32. package/corpus/core/docs/content/locales/ko-KR/cloneable-saas.mdx +2 -2
  33. package/corpus/core/docs/content/locales/ko-KR/evals.mdx +7 -0
  34. package/corpus/core/docs/content/locales/ko-KR/faq.mdx +1 -1
  35. package/corpus/core/docs/content/locales/ko-KR/template-chat.mdx +1 -1
  36. package/corpus/core/docs/content/locales/pt-BR/cloneable-saas.mdx +2 -2
  37. package/corpus/core/docs/content/locales/pt-BR/evals.mdx +8 -0
  38. package/corpus/core/docs/content/locales/pt-BR/faq.mdx +1 -1
  39. package/corpus/core/docs/content/locales/pt-BR/template-chat.mdx +1 -1
  40. package/corpus/core/docs/content/locales/zh-CN/cloneable-saas.mdx +2 -2
  41. package/corpus/core/docs/content/locales/zh-CN/evals.mdx +7 -0
  42. package/corpus/core/docs/content/locales/zh-CN/faq.mdx +1 -1
  43. package/corpus/core/docs/content/locales/zh-CN/template-chat.mdx +1 -1
  44. package/corpus/core/docs/content/locales/zh-TW/cloneable-saas.mdx +2 -2
  45. package/corpus/core/docs/content/locales/zh-TW/evals.mdx +7 -0
  46. package/corpus/core/docs/content/locales/zh-TW/faq.mdx +1 -1
  47. package/corpus/core/docs/content/locales/zh-TW/template-chat.mdx +1 -1
  48. package/corpus/core/docs/content/template-chat.mdx +1 -1
  49. package/corpus/core/package.json +1 -1
  50. package/corpus/core/src/agent/engine/builtin.ts +1 -1
  51. package/corpus/core/src/agent/engine/output-tokens.ts +1 -1
  52. package/corpus/core/src/agent/harness/acp-adapter.ts +28 -4
  53. package/corpus/core/src/agent/harness/ai-sdk-adapter.ts +3 -0
  54. package/corpus/core/src/agent/harness/translate.ts +3 -0
  55. package/corpus/core/src/agent/harness/types.ts +1 -0
  56. package/corpus/core/src/agent/model-config.ts +34 -13
  57. package/corpus/core/src/agent/production-agent.ts +87 -10
  58. package/corpus/core/src/agent/thread-data-builder.ts +29 -4
  59. package/corpus/core/src/agent/tool-call-journal.ts +109 -48
  60. package/corpus/core/src/agent/types.ts +6 -1
  61. package/corpus/core/src/cli/design-connect.ts +106 -0
  62. package/corpus/core/src/cli/gateway-helpers.ts +17 -0
  63. package/corpus/core/src/cli/recap.ts +0 -2
  64. package/corpus/core/src/cli/skills.ts +54 -16
  65. package/corpus/core/src/cli/workspace-dev.ts +29 -5
  66. package/corpus/core/src/client/AssistantChat.tsx +89 -42
  67. package/corpus/core/src/client/DefaultSpinner.tsx +8 -1
  68. package/corpus/core/src/client/chat/message-components.tsx +49 -1
  69. package/corpus/core/src/client/chat/repo-helpers.ts +71 -0
  70. package/corpus/core/src/client/chat/run-recovery.tsx +15 -5
  71. package/corpus/core/src/client/components/ApiKeySettings.tsx +8 -8
  72. package/corpus/core/src/client/components/CodeRequiredDialog.tsx +26 -15
  73. package/corpus/core/src/client/components/MissingKeyCard.tsx +13 -6
  74. package/corpus/core/src/client/composer/TiptapComposer.tsx +4 -3
  75. package/corpus/core/src/client/extensions/ExtensionsSidebarSection.tsx +0 -1
  76. package/corpus/core/src/client/guided-questions.tsx +21 -27
  77. package/corpus/core/src/client/integrations/IntegrationCard.tsx +1 -1
  78. package/corpus/core/src/client/integrations/IntegrationsPanel.tsx +1 -1
  79. package/corpus/core/src/client/onboarding/OnboardingBanner.tsx +2 -2
  80. package/corpus/core/src/client/onboarding/OnboardingPanel.tsx +23 -19
  81. package/corpus/core/src/client/resources/ResourceEditor.tsx +18 -10
  82. package/corpus/core/src/client/resources/ResourcesPanel.tsx +5 -1
  83. package/corpus/core/src/client/settings/SettingsPanel.tsx +8 -3
  84. package/corpus/core/src/client/settings/useBuilderStatus.ts +8 -41
  85. package/corpus/core/src/client/useProductionAgent.ts +6 -2
  86. package/corpus/core/src/deploy/build.ts +1 -1
  87. package/corpus/core/src/eval/define-eval.ts +4 -1
  88. package/corpus/core/src/eval/report.ts +23 -8
  89. package/corpus/core/src/eval/runner.ts +41 -6
  90. package/corpus/core/src/eval/types.ts +11 -0
  91. package/corpus/core/src/observability/traces.ts +3 -3
  92. package/corpus/core/src/onboarding/default-steps.ts +1 -1
  93. package/corpus/core/src/scripts/agent-engines/manage-agent-engine.ts +1 -1
  94. package/corpus/core/src/scripts/agent-engines/set-agent-engine.ts +1 -1
  95. package/corpus/core/src/server/agent-chat-plugin.ts +177 -81
  96. package/corpus/core/src/server/core-routes-plugin.ts +7 -1
  97. package/corpus/core/src/server/open-route.ts +59 -40
  98. package/corpus/core/src/shared/reasoning-effort.ts +2 -0
  99. package/corpus/core/src/sharing/access.ts +22 -2
  100. package/corpus/core/src/sharing/registry.ts +18 -0
  101. package/corpus/core/src/styles/agent-native.css +104 -20
  102. package/corpus/core/src/styles/rich-markdown-editor.css +11 -10
  103. package/corpus/templates/analytics/app/components/dashboard/CumulativeNetChart.tsx +10 -10
  104. package/corpus/templates/analytics/app/components/dashboard/RevenueChart.tsx +10 -10
  105. package/corpus/templates/analytics/app/components/dashboard/RevenueComparisonChart.tsx +6 -5
  106. package/corpus/templates/analytics/app/components/dashboard/TimeSeriesChart.tsx +9 -9
  107. package/corpus/templates/analytics/app/global.css +4 -0
  108. package/corpus/templates/analytics/app/lib/chart-theme.ts +13 -0
  109. package/corpus/templates/analytics/app/pages/adhoc/_shared/KpiChart.tsx +22 -24
  110. package/corpus/templates/analytics/changelog/2026-06-30-dashboard-charts-now-use-theme-aware-tooltip-and-grid-colors.md +6 -0
  111. package/corpus/templates/analytics/changelog/2026-06-30-fixed-ask-composer-spacing-so-the-chat-field-has-a-comfortab.md +6 -0
  112. package/corpus/templates/calendar/AGENTS.md +4 -0
  113. package/corpus/templates/calendar/actions/connect-google-calendar.ts +80 -0
  114. package/corpus/templates/calendar/changelog/2026-06-30-calendar-now-gives-the-agent-a-safe-google-connection-link-i.md +6 -0
  115. package/corpus/templates/calendar/server/plugins/agent-chat.ts +4 -0
  116. package/corpus/templates/content/AGENTS.md +9 -2
  117. package/corpus/templates/content/actions/_database-row-batch.ts +230 -0
  118. package/corpus/templates/content/actions/_database-utils.ts +17 -9
  119. package/corpus/templates/content/actions/_notion-action-utils.ts +26 -0
  120. package/corpus/templates/content/actions/connect-notion-status.ts +13 -4
  121. package/corpus/templates/content/actions/create-and-link-notion-page.ts +23 -0
  122. package/corpus/templates/content/actions/delete-database-items.ts +55 -0
  123. package/corpus/templates/content/actions/delete-document.ts +4 -4
  124. package/corpus/templates/content/actions/disconnect-notion.ts +16 -0
  125. package/corpus/templates/content/actions/duplicate-database-item.ts +1 -1
  126. package/corpus/templates/content/actions/duplicate-database-items.ts +191 -0
  127. package/corpus/templates/content/actions/link-notion-page.ts +10 -7
  128. package/corpus/templates/content/actions/list-notion-links.ts +3 -4
  129. package/corpus/templates/content/actions/pull-notion-page.ts +7 -9
  130. package/corpus/templates/content/actions/push-notion-page.ts +7 -9
  131. package/corpus/templates/content/actions/refresh-notion-sync-status.ts +24 -0
  132. package/corpus/templates/content/actions/resolve-notion-sync-conflict.ts +23 -0
  133. package/corpus/templates/content/actions/search-notion-pages.ts +67 -0
  134. package/corpus/templates/content/actions/unlink-notion-page.ts +23 -0
  135. package/corpus/templates/content/app/components/editor/BubbleToolbar.tsx +5 -5
  136. package/corpus/templates/content/app/components/editor/DocumentDatabase.tsx +27 -34
  137. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +16 -13
  138. package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +10 -10
  139. package/corpus/templates/content/app/components/editor/NotionConflictBanner.tsx +1 -1
  140. package/corpus/templates/content/app/components/editor/NotionSyncBar.tsx +18 -9
  141. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +27 -34
  142. package/corpus/templates/content/app/components/editor/database/navigation-state.ts +10 -4
  143. package/corpus/templates/content/app/components/sidebar/NotionButton.tsx +32 -17
  144. package/corpus/templates/content/app/global.css +6 -5
  145. package/corpus/templates/content/app/hooks/use-content-database.ts +35 -0
  146. package/corpus/templates/content/app/hooks/use-notion.ts +108 -99
  147. package/corpus/templates/content/changelog/2026-06-30-editor-floating-toolbars-now-use-theme-aware-colors-in-light.md +6 -0
  148. package/corpus/templates/content/package.json +3 -0
  149. package/corpus/templates/content/parity/README.md +69 -0
  150. package/corpus/templates/content/parity/eval-scenarios.ts +118 -0
  151. package/corpus/templates/content/parity/exceptions.allowlist.ts +17 -0
  152. package/corpus/templates/content/parity/matrix.md +28 -0
  153. package/corpus/templates/content/parity/matrix.ts +606 -0
  154. package/corpus/templates/content/parity/matrix.types.ts +42 -0
  155. package/corpus/templates/content/parity/parity-evals.eval.ts +4 -0
  156. package/corpus/templates/content/parity/render-matrix.ts +90 -0
  157. package/corpus/templates/content/parity/scenario-to-eval.ts +57 -0
  158. package/corpus/templates/content/shared/api.ts +11 -0
  159. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +6 -1
  160. package/corpus/templates/design/actions/add-localhost-screens.ts +63 -8
  161. package/corpus/templates/design/actions/apply-motion-edit.ts +12 -46
  162. package/corpus/templates/design/actions/list-design-native-assets.ts +2 -1
  163. package/corpus/templates/design/actions/migrate-board-objects-to-file.ts +49 -1
  164. package/corpus/templates/design/actions/navigate.ts +3 -12
  165. package/corpus/templates/design/actions/open-visual-edit.ts +341 -0
  166. package/corpus/templates/design/actions/view-screen.ts +1 -1
  167. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +1 -1
  168. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +345 -14
  169. package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +71 -91
  170. package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +25 -27
  171. package/corpus/templates/design/app/components/design/DeviceFrame.tsx +1 -1
  172. package/corpus/templates/design/app/components/design/DrawOverlay.tsx +2 -2
  173. package/corpus/templates/design/app/components/design/EditPanel.tsx +1111 -570
  174. package/corpus/templates/design/app/components/design/LayersPanel.tsx +162 -32
  175. package/corpus/templates/design/app/components/design/MotionDock.tsx +268 -240
  176. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +1038 -150
  177. package/corpus/templates/design/app/components/design/QuestionFlow.tsx +1 -1
  178. package/corpus/templates/design/app/components/design/ReviewPanel.tsx +81 -102
  179. package/corpus/templates/design/app/components/design/StatesPanel.tsx +6 -6
  180. package/corpus/templates/design/app/components/design/TokensPanel.tsx +11 -11
  181. package/corpus/templates/design/app/components/design/TweaksPanel.tsx +9 -7
  182. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +1129 -155
  183. package/corpus/templates/design/app/components/design/bridge/hit-test.bridge.ts +130 -37
  184. package/corpus/templates/design/app/components/design/canvas-primitive-style.ts +24 -11
  185. package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +184 -162
  186. package/corpus/templates/design/app/components/design/inspector/ConstraintsWidget.tsx +137 -79
  187. package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +13 -13
  188. package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +8 -8
  189. package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +2 -2
  190. package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +4 -4
  191. package/corpus/templates/design/app/components/design/inspector/InspectorAiActions.tsx +3 -3
  192. package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +13 -7
  193. package/corpus/templates/design/app/components/design/inspector/ShaderControls.tsx +14 -11
  194. package/corpus/templates/design/app/components/design/inspector/ShaderFillsPanel.tsx +4 -4
  195. package/corpus/templates/design/app/components/design/inspector/index.ts +2 -0
  196. package/corpus/templates/design/app/components/design/types.ts +19 -0
  197. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +61 -78
  198. package/corpus/templates/design/app/components/layout/Header.tsx +0 -1
  199. package/corpus/templates/design/app/components/layout/Layout.tsx +3 -2
  200. package/corpus/templates/design/app/components/layout/Sidebar.tsx +0 -2
  201. package/corpus/templates/design/app/components/visual-editor/CanvasCommentPins.tsx +5 -4
  202. package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +1 -1
  203. package/corpus/templates/design/app/components/visual-editor/SaveStatusIndicator.tsx +2 -2
  204. package/corpus/templates/design/app/global.css +56 -0
  205. package/corpus/templates/design/app/hooks/use-agent-generating.ts +4 -5
  206. package/corpus/templates/design/app/hooks/use-navigation-state.ts +6 -7
  207. package/corpus/templates/design/app/hooks/use-question-flow.ts +3 -2
  208. package/corpus/templates/design/app/hooks/useAgentEditRequest.ts +6 -4
  209. package/corpus/templates/design/app/i18n/zh-TW.ts +5 -14
  210. package/corpus/templates/design/app/i18n-data.ts +63 -188
  211. package/corpus/templates/design/app/lib/agent-chat.ts +13 -0
  212. package/corpus/templates/design/app/pages/DesignEditor.tsx +1428 -384
  213. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +9 -5
  214. package/corpus/templates/design/app/pages/DesignSystems.tsx +2 -2
  215. package/corpus/templates/design/app/pages/Index.tsx +49 -26
  216. package/corpus/templates/design/app/pages/NotFound.tsx +25 -8
  217. package/corpus/templates/design/app/pages/VisualEdit.tsx +17 -5
  218. package/corpus/templates/design/app/routes/examples.tsx +1 -7
  219. package/corpus/templates/design/app/routes/templates.tsx +7 -4
  220. package/corpus/templates/design/changelog/2026-06-30-board-shapes-and-auto-layout-controls-are-clearer.md +6 -0
  221. package/corpus/templates/design/changelog/2026-06-30-component-selections-now-use-purple-component-chrome-and-sho.md +6 -0
  222. package/corpus/templates/design/changelog/2026-06-30-constraints-now-stay-tucked-into-a-compact-inspector-preview.md +6 -0
  223. package/corpus/templates/design/changelog/2026-06-30-creating-a-component-now-opens-in-a-compact-inspector-popove.md +6 -0
  224. package/corpus/templates/design/changelog/2026-06-30-design-cards-no-longer-show-legacy-project-type-badges.md +6 -0
  225. package/corpus/templates/design/changelog/2026-06-30-design-chat-now-keeps-new-turns-in-the-visible-design-agent-.md +6 -0
  226. package/corpus/templates/design/changelog/2026-06-30-design-editor-panels-now-keep-their-compact-text-sizing-cons.md +6 -0
  227. package/corpus/templates/design/changelog/2026-06-30-design-no-longer-shows-the-connected-local-code-warning-bann.md +6 -0
  228. package/corpus/templates/design/changelog/2026-06-30-design-now-opens-to-the-files-panel-unless-a-generation-is-a.md +6 -0
  229. package/corpus/templates/design/changelog/2026-06-30-design-opens-with-a-cleaner-empty-canvas-and-loading-preview.md +6 -0
  230. package/corpus/templates/design/changelog/2026-06-30-design-tools-use-simpler-less-decorative-icons.md +6 -0
  231. package/corpus/templates/design/changelog/2026-06-30-dragging-absolute-elements-no-longer-shows-coordinate-labels.md +6 -0
  232. package/corpus/templates/design/changelog/2026-06-30-fixed-all-screens-opening-too-zoomed-in-by-default.md +6 -0
  233. package/corpus/templates/design/changelog/2026-06-30-fixed-the-public-design-assets-sidebar-so-native-components-.md +6 -0
  234. package/corpus/templates/design/changelog/2026-06-30-fixed-the-screen-overview-board-so-empty-board-space-no-long.md +6 -0
  235. package/corpus/templates/design/changelog/2026-06-30-full-view-screens-can-now-scroll-while-remaining-editable.md +6 -0
  236. package/corpus/templates/design/changelog/2026-06-30-inspector-element-headers-show-the-selected-html-tag-and-the.md +6 -0
  237. package/corpus/templates/design/changelog/2026-06-30-inspector-inputs-stay-compact-across-desktop-breakpoints.md +6 -0
  238. package/corpus/templates/design/changelog/2026-06-30-layers-can-be-multi-selected-from-the-canvas-and-edited-toge.md +6 -0
  239. package/corpus/templates/design/changelog/2026-06-30-local-visual-edit-links-can-edit-localhost-frames-without-si.md +6 -0
  240. package/corpus/templates/design/changelog/2026-06-30-localhost-visual-edit-frames-can-now-be-selected-and-edited.md +6 -0
  241. package/corpus/templates/design/changelog/2026-06-30-marquee-selection-now-works-inside-screens-multi-selected-la.md +6 -0
  242. package/corpus/templates/design/changelog/2026-06-30-motion-is-now-available-from-the-persistent-left-rail-and-th.md +6 -0
  243. package/corpus/templates/design/changelog/2026-06-30-motion-timeline-collapse-and-reopen-animations-feel-smoother.md +6 -0
  244. package/corpus/templates/design/changelog/2026-06-30-multi-select-outlines-now-stay-consistent-across-all-screens.md +6 -0
  245. package/corpus/templates/design/changelog/2026-06-30-new-board-shapes-now-start-with-neutral-gray-styling.md +6 -0
  246. package/corpus/templates/design/changelog/2026-06-30-new-designs-open-into-a-steadier-loading-state-before-the-ed.md +6 -0
  247. package/corpus/templates/design/changelog/2026-06-30-new-designs-show-a-loading-state-during-handoff-and-keep-edi.md +6 -0
  248. package/corpus/templates/design/changelog/2026-06-30-public-visual-edit-design-links-now-open-directly-instead-of.md +6 -0
  249. package/corpus/templates/design/changelog/2026-06-30-removed-the-confusing-states-section-from-the-design-editor-.md +6 -0
  250. package/corpus/templates/design/changelog/2026-06-30-removed-the-templates-gallery-from-design-navigation.md +6 -0
  251. package/corpus/templates/design/changelog/2026-06-30-share-stays-visible-as-soon-as-editable-designs-load.md +6 -0
  252. package/corpus/templates/design/changelog/2026-06-30-signed-out-save-and-share-controls-use-simpler-labels-and-op.md +6 -0
  253. package/corpus/templates/design/changelog/2026-06-30-text-added-on-the-canvas-now-focuses-cleanly-with-the-right-.md +6 -0
  254. package/corpus/templates/design/changelog/2026-06-30-the-design-editor-loading-skeleton-is-simpler-and-its-bottom.md +6 -0
  255. package/corpus/templates/design/changelog/2026-06-30-the-design-editor-loading-skeleton-now-follows-the-current-t.md +6 -0
  256. package/corpus/templates/design/changelog/2026-06-30-the-design-inspector-no-longer-shows-child-layout-controls-o.md +6 -0
  257. package/corpus/templates/design/changelog/2026-06-30-the-design-inspector-no-longer-shows-the-ask-ai-section-abov.md +6 -0
  258. package/corpus/templates/design/changelog/2026-06-30-the-design-review-panel-no-longer-shows-a-separate-inline-au.md +6 -0
  259. package/corpus/templates/design/changelog/2026-06-30-the-empty-designs-page-now-focuses-on-a-single-primary-new-d.md +6 -0
  260. package/corpus/templates/design/changelog/2026-06-30-the-layers-panel-header-stays-as-layers-while-multiple-items.md +6 -0
  261. package/corpus/templates/design/changelog/2026-06-30-the-missing-design-screen-now-uses-a-neutral-back-button.md +6 -0
  262. package/corpus/templates/design/changelog/2026-06-30-the-motion-timeline-now-closes-without-squeezing-the-canvas-.md +6 -0
  263. package/corpus/templates/design/changelog/2026-06-30-the-new-design-connect-ai-setup-now-lines-up-with-the-compos.md +6 -0
  264. package/corpus/templates/design/changelog/2026-06-30-the-screen-overview-board-now-blends-into-the-canvas-and-new.md +6 -0
  265. package/corpus/templates/design/changelog/2026-06-30-top-level-canvas-drops-now-show-screen-guides.md +6 -0
  266. package/corpus/templates/design/changelog/2026-06-30-top-level-canvas-layers-now-keep-a-transparent-backdrop-and-.md +6 -0
  267. package/corpus/templates/design/changelog/2026-06-30-top-level-canvas-layers-now-select-reliably-from-all-screens.md +6 -0
  268. package/corpus/templates/design/changelog/2026-06-30-visual-edit-can-open-and-refresh-localhost-screens-in-one-au.md +6 -0
  269. package/corpus/templates/design/e2e/helpers.ts +15 -4
  270. package/corpus/templates/design/server/db/index.ts +52 -0
  271. package/corpus/templates/design/server/plugins/agent-chat.ts +5 -0
  272. package/corpus/templates/design/server/plugins/auth.ts +1 -0
  273. package/corpus/templates/design/server/plugins/core-routes.ts +4 -0
  274. package/corpus/templates/design/shared/board-file.ts +380 -5
  275. package/corpus/templates/design/shared/board-objects.ts +2 -2
  276. package/corpus/templates/design/shared/code-layer.ts +50 -6
  277. package/corpus/templates/design/shared/motion-compiler.ts +27 -0
  278. package/corpus/templates/macros/app/components/DailyProgress.tsx +41 -37
  279. package/corpus/templates/macros/app/components/ExerciseCard.tsx +2 -2
  280. package/corpus/templates/macros/app/components/MealCard.tsx +2 -2
  281. package/corpus/templates/macros/app/components/VoiceDictation.tsx +1 -1
  282. package/corpus/templates/macros/app/components/WeeklyCaloriesChart.tsx +1 -1
  283. package/corpus/templates/macros/app/components/WeightCard.tsx +2 -2
  284. package/corpus/templates/macros/app/components/WeightTracker.tsx +1 -1
  285. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +1 -1
  286. package/corpus/templates/macros/app/routes/_index.tsx +5 -5
  287. package/corpus/templates/macros/app/routes/analytics.tsx +1 -1
  288. package/corpus/templates/macros/changelog/2026-06-30-dashboard-loading-and-chart-surfaces-now-use-theme-aware-col.md +6 -0
  289. package/corpus/templates/mail/app/components/email/ComposeBubbleToolbar.tsx +14 -11
  290. package/corpus/templates/mail/app/global.css +3 -2
  291. package/corpus/templates/mail/changelog/2026-06-30-compose-floating-toolbars-now-use-theme-aware-colors-in-ligh.md +6 -0
  292. package/corpus/templates/plan/app/pages/PlansPage.tsx +2 -2
  293. package/corpus/templates/slides/app/components/deck/DeckCard.tsx +3 -3
  294. package/corpus/templates/slides/app/global.css +10 -0
  295. package/corpus/templates/slides/app/pages/Index.tsx +55 -51
  296. package/corpus/templates/slides/changelog/2026-06-30-deck-thumbnails-collapse-cleanly-to-one-column-when-the-chat.md +6 -0
  297. package/dist/agent/engine/anthropic-engine.d.ts +2 -2
  298. package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
  299. package/dist/agent/engine/builder-engine.d.ts +2 -2
  300. package/dist/agent/engine/builder-engine.d.ts.map +1 -1
  301. package/dist/agent/engine/builtin.js +1 -1
  302. package/dist/agent/engine/builtin.js.map +1 -1
  303. package/dist/agent/engine/output-tokens.js +1 -1
  304. package/dist/agent/engine/output-tokens.js.map +1 -1
  305. package/dist/agent/harness/acp-adapter.d.ts +4 -1
  306. package/dist/agent/harness/acp-adapter.d.ts.map +1 -1
  307. package/dist/agent/harness/acp-adapter.js +19 -2
  308. package/dist/agent/harness/acp-adapter.js.map +1 -1
  309. package/dist/agent/harness/ai-sdk-adapter.d.ts.map +1 -1
  310. package/dist/agent/harness/ai-sdk-adapter.js +3 -0
  311. package/dist/agent/harness/ai-sdk-adapter.js.map +1 -1
  312. package/dist/agent/harness/translate.d.ts.map +1 -1
  313. package/dist/agent/harness/translate.js +3 -0
  314. package/dist/agent/harness/translate.js.map +1 -1
  315. package/dist/agent/harness/types.d.ts +1 -0
  316. package/dist/agent/harness/types.d.ts.map +1 -1
  317. package/dist/agent/harness/types.js.map +1 -1
  318. package/dist/agent/model-config.d.ts +21 -20
  319. package/dist/agent/model-config.d.ts.map +1 -1
  320. package/dist/agent/model-config.js +31 -13
  321. package/dist/agent/model-config.js.map +1 -1
  322. package/dist/agent/production-agent.d.ts.map +1 -1
  323. package/dist/agent/production-agent.js +85 -10
  324. package/dist/agent/production-agent.js.map +1 -1
  325. package/dist/agent/thread-data-builder.d.ts.map +1 -1
  326. package/dist/agent/thread-data-builder.js +27 -6
  327. package/dist/agent/thread-data-builder.js.map +1 -1
  328. package/dist/agent/tool-call-journal.d.ts +11 -9
  329. package/dist/agent/tool-call-journal.d.ts.map +1 -1
  330. package/dist/agent/tool-call-journal.js +92 -40
  331. package/dist/agent/tool-call-journal.js.map +1 -1
  332. package/dist/agent/types.d.ts +5 -1
  333. package/dist/agent/types.d.ts.map +1 -1
  334. package/dist/agent/types.js.map +1 -1
  335. package/dist/cli/design-connect.d.ts.map +1 -1
  336. package/dist/cli/design-connect.js +84 -0
  337. package/dist/cli/design-connect.js.map +1 -1
  338. package/dist/cli/gateway-helpers.d.ts +4 -0
  339. package/dist/cli/gateway-helpers.d.ts.map +1 -1
  340. package/dist/cli/gateway-helpers.js +9 -0
  341. package/dist/cli/gateway-helpers.js.map +1 -1
  342. package/dist/cli/recap.d.ts.map +1 -1
  343. package/dist/cli/recap.js +0 -2
  344. package/dist/cli/recap.js.map +1 -1
  345. package/dist/cli/skills.d.ts.map +1 -1
  346. package/dist/cli/skills.js +54 -16
  347. package/dist/cli/skills.js.map +1 -1
  348. package/dist/cli/workspace-dev.d.ts.map +1 -1
  349. package/dist/cli/workspace-dev.js +33 -6
  350. package/dist/cli/workspace-dev.js.map +1 -1
  351. package/dist/client/AssistantChat.d.ts.map +1 -1
  352. package/dist/client/AssistantChat.js +72 -26
  353. package/dist/client/AssistantChat.js.map +1 -1
  354. package/dist/client/DefaultSpinner.d.ts.map +1 -1
  355. package/dist/client/DefaultSpinner.js +8 -1
  356. package/dist/client/DefaultSpinner.js.map +1 -1
  357. package/dist/client/chat/message-components.d.ts +7 -1
  358. package/dist/client/chat/message-components.d.ts.map +1 -1
  359. package/dist/client/chat/message-components.js +37 -1
  360. package/dist/client/chat/message-components.js.map +1 -1
  361. package/dist/client/chat/repo-helpers.d.ts +1 -0
  362. package/dist/client/chat/repo-helpers.d.ts.map +1 -1
  363. package/dist/client/chat/repo-helpers.js +59 -0
  364. package/dist/client/chat/repo-helpers.js.map +1 -1
  365. package/dist/client/chat/run-recovery.d.ts.map +1 -1
  366. package/dist/client/chat/run-recovery.js +4 -4
  367. package/dist/client/chat/run-recovery.js.map +1 -1
  368. package/dist/client/components/ApiKeySettings.js +8 -8
  369. package/dist/client/components/ApiKeySettings.js.map +1 -1
  370. package/dist/client/components/CodeRequiredDialog.d.ts.map +1 -1
  371. package/dist/client/components/CodeRequiredDialog.js +24 -15
  372. package/dist/client/components/CodeRequiredDialog.js.map +1 -1
  373. package/dist/client/components/MissingKeyCard.d.ts.map +1 -1
  374. package/dist/client/components/MissingKeyCard.js +11 -6
  375. package/dist/client/components/MissingKeyCard.js.map +1 -1
  376. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  377. package/dist/client/composer/TiptapComposer.js +4 -3
  378. package/dist/client/composer/TiptapComposer.js.map +1 -1
  379. package/dist/client/extensions/ExtensionsSidebarSection.d.ts.map +1 -1
  380. package/dist/client/extensions/ExtensionsSidebarSection.js +1 -1
  381. package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
  382. package/dist/client/guided-questions.d.ts.map +1 -1
  383. package/dist/client/guided-questions.js +6 -6
  384. package/dist/client/guided-questions.js.map +1 -1
  385. package/dist/client/integrations/IntegrationCard.js +1 -1
  386. package/dist/client/integrations/IntegrationCard.js.map +1 -1
  387. package/dist/client/integrations/IntegrationsPanel.js +1 -1
  388. package/dist/client/integrations/IntegrationsPanel.js.map +1 -1
  389. package/dist/client/onboarding/OnboardingBanner.js +2 -2
  390. package/dist/client/onboarding/OnboardingBanner.js.map +1 -1
  391. package/dist/client/onboarding/OnboardingPanel.js +23 -19
  392. package/dist/client/onboarding/OnboardingPanel.js.map +1 -1
  393. package/dist/client/resources/ResourceEditor.d.ts.map +1 -1
  394. package/dist/client/resources/ResourceEditor.js +13 -10
  395. package/dist/client/resources/ResourceEditor.js.map +1 -1
  396. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  397. package/dist/client/resources/ResourcesPanel.js +2 -1
  398. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  399. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  400. package/dist/client/settings/SettingsPanel.js +8 -3
  401. package/dist/client/settings/SettingsPanel.js.map +1 -1
  402. package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
  403. package/dist/client/settings/useBuilderStatus.js +6 -38
  404. package/dist/client/settings/useBuilderStatus.js.map +1 -1
  405. package/dist/client/useProductionAgent.d.ts +2 -1
  406. package/dist/client/useProductionAgent.d.ts.map +1 -1
  407. package/dist/client/useProductionAgent.js.map +1 -1
  408. package/dist/collab/awareness.d.ts +2 -2
  409. package/dist/collab/awareness.d.ts.map +1 -1
  410. package/dist/collab/routes.d.ts +1 -1
  411. package/dist/deploy/build.js +1 -1
  412. package/dist/deploy/build.js.map +1 -1
  413. package/dist/eval/define-eval.d.ts.map +1 -1
  414. package/dist/eval/define-eval.js +2 -1
  415. package/dist/eval/define-eval.js.map +1 -1
  416. package/dist/eval/report.d.ts.map +1 -1
  417. package/dist/eval/report.js +19 -4
  418. package/dist/eval/report.js.map +1 -1
  419. package/dist/eval/runner.d.ts.map +1 -1
  420. package/dist/eval/runner.js +38 -6
  421. package/dist/eval/runner.js.map +1 -1
  422. package/dist/eval/types.d.ts +11 -0
  423. package/dist/eval/types.d.ts.map +1 -1
  424. package/dist/eval/types.js.map +1 -1
  425. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  426. package/dist/notifications/routes.d.ts +3 -3
  427. package/dist/observability/routes.d.ts +5 -5
  428. package/dist/observability/traces.d.ts.map +1 -1
  429. package/dist/observability/traces.js.map +1 -1
  430. package/dist/onboarding/default-steps.js +1 -1
  431. package/dist/onboarding/default-steps.js.map +1 -1
  432. package/dist/progress/routes.d.ts +1 -1
  433. package/dist/resources/handlers.d.ts +1 -1
  434. package/dist/scripts/agent-engines/manage-agent-engine.js +1 -1
  435. package/dist/scripts/agent-engines/manage-agent-engine.js.map +1 -1
  436. package/dist/scripts/agent-engines/set-agent-engine.js +1 -1
  437. package/dist/scripts/agent-engines/set-agent-engine.js.map +1 -1
  438. package/dist/server/agent-chat-plugin.d.ts +3 -0
  439. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  440. package/dist/server/agent-chat-plugin.js +134 -72
  441. package/dist/server/agent-chat-plugin.js.map +1 -1
  442. package/dist/server/core-routes-plugin.d.ts +3 -0
  443. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  444. package/dist/server/core-routes-plugin.js +4 -1
  445. package/dist/server/core-routes-plugin.js.map +1 -1
  446. package/dist/server/open-route.d.ts +9 -0
  447. package/dist/server/open-route.d.ts.map +1 -1
  448. package/dist/server/open-route.js +48 -38
  449. package/dist/server/open-route.js.map +1 -1
  450. package/dist/shared/reasoning-effort.js +3 -0
  451. package/dist/shared/reasoning-effort.js.map +1 -1
  452. package/dist/sharing/access.d.ts.map +1 -1
  453. package/dist/sharing/access.js +18 -2
  454. package/dist/sharing/access.js.map +1 -1
  455. package/dist/sharing/registry.d.ts +10 -0
  456. package/dist/sharing/registry.d.ts.map +1 -1
  457. package/dist/sharing/registry.js.map +1 -1
  458. package/dist/styles/agent-native.css +104 -20
  459. package/dist/styles/rich-markdown-editor.css +11 -10
  460. package/docs/content/cloneable-saas.mdx +2 -2
  461. package/docs/content/evals.mdx +34 -12
  462. package/docs/content/faq.mdx +1 -1
  463. package/docs/content/locales/ar-SA/cloneable-saas.mdx +2 -2
  464. package/docs/content/locales/ar-SA/evals.mdx +7 -0
  465. package/docs/content/locales/ar-SA/faq.mdx +1 -1
  466. package/docs/content/locales/ar-SA/template-chat.mdx +1 -1
  467. package/docs/content/locales/de-DE/cloneable-saas.mdx +2 -2
  468. package/docs/content/locales/de-DE/evals.mdx +8 -0
  469. package/docs/content/locales/de-DE/faq.mdx +1 -1
  470. package/docs/content/locales/de-DE/template-chat.mdx +1 -1
  471. package/docs/content/locales/es-ES/cloneable-saas.mdx +2 -2
  472. package/docs/content/locales/es-ES/evals.mdx +8 -0
  473. package/docs/content/locales/es-ES/faq.mdx +1 -1
  474. package/docs/content/locales/es-ES/template-chat.mdx +1 -1
  475. package/docs/content/locales/fr-FR/cloneable-saas.mdx +2 -2
  476. package/docs/content/locales/fr-FR/evals.mdx +8 -0
  477. package/docs/content/locales/fr-FR/faq.mdx +1 -1
  478. package/docs/content/locales/fr-FR/template-chat.mdx +1 -1
  479. package/docs/content/locales/hi-IN/cloneable-saas.mdx +2 -2
  480. package/docs/content/locales/hi-IN/evals.mdx +8 -0
  481. package/docs/content/locales/hi-IN/faq.mdx +1 -1
  482. package/docs/content/locales/hi-IN/template-chat.mdx +1 -1
  483. package/docs/content/locales/ja-JP/cloneable-saas.mdx +2 -2
  484. package/docs/content/locales/ja-JP/evals.mdx +7 -0
  485. package/docs/content/locales/ja-JP/faq.mdx +1 -1
  486. package/docs/content/locales/ja-JP/template-chat.mdx +1 -1
  487. package/docs/content/locales/ko-KR/cloneable-saas.mdx +2 -2
  488. package/docs/content/locales/ko-KR/evals.mdx +7 -0
  489. package/docs/content/locales/ko-KR/faq.mdx +1 -1
  490. package/docs/content/locales/ko-KR/template-chat.mdx +1 -1
  491. package/docs/content/locales/pt-BR/cloneable-saas.mdx +2 -2
  492. package/docs/content/locales/pt-BR/evals.mdx +8 -0
  493. package/docs/content/locales/pt-BR/faq.mdx +1 -1
  494. package/docs/content/locales/pt-BR/template-chat.mdx +1 -1
  495. package/docs/content/locales/zh-CN/cloneable-saas.mdx +2 -2
  496. package/docs/content/locales/zh-CN/evals.mdx +7 -0
  497. package/docs/content/locales/zh-CN/faq.mdx +1 -1
  498. package/docs/content/locales/zh-CN/template-chat.mdx +1 -1
  499. package/docs/content/locales/zh-TW/cloneable-saas.mdx +2 -2
  500. package/docs/content/locales/zh-TW/evals.mdx +7 -0
  501. package/docs/content/locales/zh-TW/faq.mdx +1 -1
  502. package/docs/content/locales/zh-TW/template-chat.mdx +1 -1
  503. package/docs/content/template-chat.mdx +1 -1
  504. package/package.json +1 -1
  505. package/corpus/templates/content/server/routes/api/notion/disconnect.post.ts +0 -12
  506. package/corpus/templates/design/app/components/design/LocalSourceEditBanner.tsx +0 -157
  507. package/corpus/templates/design/app/lib/design-templates.ts +0 -1305
  508. package/corpus/templates/design/app/pages/Templates.tsx +0 -279
@@ -0,0 +1,80 @@
1
+ import { defineAction } from "@agent-native/core";
2
+ import { getRequestUserEmail } from "@agent-native/core/server";
3
+ import { z } from "zod";
4
+
5
+ const CONNECT_PATH = "/_agent-native/google/auth-url";
6
+ const ADD_ACCOUNT_PATH = "/_agent-native/google/add-account/auth-url";
7
+
8
+ function normalizeReturnPath(value: string | undefined): string | undefined {
9
+ if (!value) return undefined;
10
+ try {
11
+ const url = new URL(value, "https://calendar.agent-native.local");
12
+ if (url.origin !== "https://calendar.agent-native.local") {
13
+ return undefined;
14
+ }
15
+ return `${url.pathname}${url.search}${url.hash}`;
16
+ } catch {
17
+ return undefined;
18
+ }
19
+ }
20
+
21
+ export default defineAction({
22
+ description:
23
+ "Create a user-clickable Google Calendar OAuth link. Use this when the user asks to connect or reconnect Google Calendar. Do not fetch the returned URL as an API; the signed-in user must open it in their browser.",
24
+ schema: z.object({
25
+ addAccount: z
26
+ .boolean()
27
+ .optional()
28
+ .describe(
29
+ "Use true only when adding another Google Calendar account to an already connected Calendar workspace.",
30
+ ),
31
+ returnPath: z
32
+ .string()
33
+ .optional()
34
+ .describe(
35
+ "Optional same-origin Calendar path to return to after the Google OAuth flow.",
36
+ ),
37
+ }),
38
+ http: { method: "GET" },
39
+ readOnly: true,
40
+ parallelSafe: true,
41
+ run: async (args) => {
42
+ const owner = getRequestUserEmail();
43
+ if (!owner) {
44
+ throw new Error("Sign in to Calendar before connecting Google Calendar.");
45
+ }
46
+
47
+ const path = args.addAccount ? ADD_ACCOUNT_PATH : CONNECT_PATH;
48
+ const params = new URLSearchParams({ redirect: "1" });
49
+ if (!args.addAccount) params.set("calendar", "1");
50
+
51
+ const returnPath = normalizeReturnPath(args.returnPath);
52
+ if (returnPath) params.set("return", returnPath);
53
+
54
+ const url = `${path}?${params.toString()}`;
55
+ const label = args.addAccount
56
+ ? "Add Google Calendar account"
57
+ : "Connect Google Calendar";
58
+ return {
59
+ provider: "google_calendar",
60
+ url,
61
+ label,
62
+ markdown: `[${label}](${url})`,
63
+ message:
64
+ "Open this link in the signed-in Calendar browser session to connect Google Calendar. Do not fetch it from the agent backend.",
65
+ requiresUserGesture: true,
66
+ };
67
+ },
68
+ link: ({ result }) => {
69
+ const url =
70
+ result && typeof result === "object"
71
+ ? (result as { url?: unknown }).url
72
+ : null;
73
+ if (typeof url !== "string" || !url) return null;
74
+ return {
75
+ url,
76
+ label: "Connect Google Calendar",
77
+ view: "settings",
78
+ };
79
+ },
80
+ });
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-06-30
4
+ ---
5
+
6
+ Calendar now gives the agent a safe Google connection link instead of surfacing a raw auth error.
@@ -70,6 +70,7 @@ const INITIAL_TOOL_NAMES = [
70
70
  "find-a-time",
71
71
  "search-people",
72
72
  "navigate",
73
+ "connect-google-calendar",
73
74
  "list-booking-links",
74
75
  "create-booking-link",
75
76
  "update-booking-link",
@@ -111,6 +112,7 @@ Provider-specific Calendar actions are shortcuts, not limits. If a first-class a
111
112
  - \`pnpm action navigate --view=calendar --date=YYYY-MM-DD\` — Navigate to a specific date
112
113
  - \`pnpm action navigate --view=availability\` — Show availability settings
113
114
  - \`pnpm action navigate --view=booking-links\` — Show booking links
115
+ - \`pnpm action connect-google-calendar\` — Create a user-clickable Google Calendar OAuth link. Use this when the user asks to connect or reconnect Google Calendar. Do not fetch \`/_agent-native/google/auth-url\` yourself; OAuth must be opened by the signed-in user in their browser.
114
116
  - \`pnpm action update-calendar-visual-preferences --colorMode multi\` — Color the local app UI by meeting type without modifying Google Calendar events
115
117
  - \`pnpm action update-calendar-visual-preferences --colorMode single --singleColor '#5B9BD5'\` — Use one local display color for the user's Google events
116
118
  - \`pnpm action check-availability --date YYYY-MM-DD --duration 60\` — Check free slots
@@ -125,6 +127,8 @@ Use \`create-event\` or \`update-event --colorId 1..11\` when the user wants one
125
127
  ## Google Connection Check
126
128
  Before answering schedule questions, run view-screen first for context, then use list-events for the requested date range even if the user is currently on Settings, Booking Links, or another non-calendar page. Do not infer a Google Calendar connection problem just because the current page is Settings. Only ask the user to reconnect Google if list-events or the explicit Google status reports an auth/connection error.
127
129
 
130
+ When the user explicitly asks you to connect or reconnect Google Calendar, call \`connect-google-calendar\` and give them the returned link. Do not call raw HTTP/fetch/web-request against \`/_agent-native/google/auth-url\`; that route depends on the user's browser session and will return 401 from the agent backend.
131
+
128
132
  For relationship-history or frequency questions such as "who have I met at Adobe?" or "how often do I meet with Mattel?", prefer the raw Google Calendar API through provider-api-request so you can choose the exact timeMin/timeMax, q, calendarId, maxResults, and pageToken behavior. Stage large paginated results before analysis. Do not conclude there are no recurring meetings from the visible range or from a convenience action alone.
129
133
 
130
134
  ## Context Awareness
@@ -121,7 +121,9 @@ cd templates/content && pnpm action <name> [args]
121
121
  | `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 |
122
122
  | `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` |
123
123
  | `add-database-item` | `--databaseId <id> [--title <text>] [--propertyValues <json>]` | Add a page row to a database, optionally seeding property values |
124
- | `duplicate-database-item` | `--itemId <id>` or `--documentId <id> [--title <text>]` | Duplicate a database row page and its stored property values |
124
+ | `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 |
125
+ | `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 |
126
+ | `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 |
125
127
  | `move-database-item` | `--itemId <id>` or `--documentId <id> --position <number>` | Move a database row page to a new zero-based table position |
126
128
  | `update-content-database-view` | `--databaseId <id> --viewConfig <json>` | Persist database views, sorts, filters, hidden properties, and view settings |
127
129
  | `list-document-properties` | `--documentId <id> [--format json]` | List Notion-style property definitions and values for a document |
@@ -568,11 +570,16 @@ multi-select, users can add a new board group from the board itself; this
568
570
  appends a new option to the grouped property definition.
569
571
  Use
570
572
  `create-content-database`, `get-content-database`,
571
- `add-database-item`, `duplicate-database-item`, `move-database-item`,
573
+ `add-database-item`, `duplicate-database-item`, `duplicate-database-items`,
574
+ `delete-database-items`, `move-database-item`,
572
575
  `update-content-database-view`, `list-document-properties`,
573
576
  `configure-document-property`, `set-document-property`,
574
577
  `duplicate-document-property`, and `delete-document-property`; do not edit
575
578
  property rows or view config via raw SQL when an action can do it.
579
+ When targeting more than one database row, call `duplicate-database-items` or
580
+ `delete-database-items` once with a native JSON array of `itemIds` or
581
+ `documentIds`. Do not loop `duplicate-database-item` or `delete-document` for
582
+ multi-row duplicate/delete requests.
576
583
 
577
584
  ## UI Components
578
585
 
@@ -0,0 +1,230 @@
1
+ import { and, asc, eq, inArray, isNull, or, sql } from "drizzle-orm";
2
+ import { z } from "zod";
3
+
4
+ import { getDb, schema } from "../server/db/index.js";
5
+
6
+ export const DATABASE_ROW_BATCH_LIMIT = 100;
7
+
8
+ export const databaseRowBatchSchema = z
9
+ .object({
10
+ databaseId: z.string().optional().describe("Content database ID"),
11
+ documentId: z
12
+ .string()
13
+ .optional()
14
+ .describe("Content database backing document ID"),
15
+ itemIds: z
16
+ .array(z.string())
17
+ .max(DATABASE_ROW_BATCH_LIMIT)
18
+ .optional()
19
+ .describe(
20
+ 'Native JSON array of database row item IDs to mutate in one batch, for example ["item_1", "item_2"].',
21
+ ),
22
+ documentIds: z
23
+ .array(z.string())
24
+ .max(DATABASE_ROW_BATCH_LIMIT)
25
+ .optional()
26
+ .describe(
27
+ 'Native JSON array of database row document IDs to mutate in one batch, for example ["doc_1", "doc_2"].',
28
+ ),
29
+ })
30
+ .superRefine((value, ctx) => {
31
+ if (!value.databaseId && !value.documentId) {
32
+ ctx.addIssue({
33
+ code: z.ZodIssueCode.custom,
34
+ message: "Either databaseId or documentId is required.",
35
+ });
36
+ }
37
+ const total =
38
+ (value.itemIds?.length ?? 0) + (value.documentIds?.length ?? 0);
39
+ if (total === 0) {
40
+ ctx.addIssue({
41
+ code: z.ZodIssueCode.custom,
42
+ message: "At least one itemId or documentId is required.",
43
+ });
44
+ }
45
+ if (total > DATABASE_ROW_BATCH_LIMIT) {
46
+ ctx.addIssue({
47
+ code: z.ZodIssueCode.custom,
48
+ message: `Database row batch is limited to ${DATABASE_ROW_BATCH_LIMIT} rows.`,
49
+ });
50
+ }
51
+ });
52
+
53
+ export type DatabaseRowBatchInput = z.infer<typeof databaseRowBatchSchema>;
54
+
55
+ export type DatabaseRowBatchRow = {
56
+ item: typeof schema.contentDatabaseItems.$inferSelect;
57
+ database: typeof schema.contentDatabases.$inferSelect;
58
+ document: typeof schema.documents.$inferSelect;
59
+ };
60
+
61
+ function findDuplicates(values: string[]) {
62
+ const seen = new Set<string>();
63
+ const duplicates = new Set<string>();
64
+ for (const value of values) {
65
+ if (seen.has(value)) duplicates.add(value);
66
+ seen.add(value);
67
+ }
68
+ return [...duplicates];
69
+ }
70
+
71
+ function positionCaseSql(
72
+ idColumn: unknown,
73
+ fallbackColumn: unknown,
74
+ orderedIds: string[],
75
+ ) {
76
+ const cases = orderedIds.map((id, index) => sql`WHEN ${id} THEN ${index}`);
77
+ return sql<number>`CASE ${idColumn} ${sql.join(cases, sql` `)} ELSE ${fallbackColumn} END`;
78
+ }
79
+
80
+ export async function resolveDatabaseRowsForBatch(
81
+ input: DatabaseRowBatchInput,
82
+ ): Promise<{
83
+ database: typeof schema.contentDatabases.$inferSelect;
84
+ rows: DatabaseRowBatchRow[];
85
+ }> {
86
+ const itemIds = input.itemIds ?? [];
87
+ const documentIds = input.documentIds ?? [];
88
+ const requestedCount = itemIds.length + documentIds.length;
89
+ if (!input.databaseId && !input.documentId) {
90
+ throw new Error("Either databaseId or documentId is required.");
91
+ }
92
+ if (requestedCount === 0) {
93
+ throw new Error("At least one itemId or documentId is required.");
94
+ }
95
+ if (requestedCount > DATABASE_ROW_BATCH_LIMIT) {
96
+ throw new Error(
97
+ `Database row batch is limited to ${DATABASE_ROW_BATCH_LIMIT} rows.`,
98
+ );
99
+ }
100
+ const duplicateItemIds = findDuplicates(itemIds);
101
+ const duplicateDocumentIds = findDuplicates(documentIds);
102
+ if (duplicateItemIds.length > 0 || duplicateDocumentIds.length > 0) {
103
+ throw new Error("Duplicate database row IDs are not allowed in one batch.");
104
+ }
105
+
106
+ const db = getDb();
107
+ const [database] = await db
108
+ .select()
109
+ .from(schema.contentDatabases)
110
+ .where(
111
+ and(
112
+ input.databaseId
113
+ ? eq(schema.contentDatabases.id, input.databaseId)
114
+ : undefined,
115
+ input.documentId
116
+ ? eq(schema.contentDatabases.documentId, input.documentId)
117
+ : undefined,
118
+ isNull(schema.contentDatabases.deletedAt),
119
+ ),
120
+ );
121
+
122
+ if (!database) throw new Error("Database not found.");
123
+
124
+ const rowPredicates = [];
125
+ if (itemIds.length > 0) {
126
+ rowPredicates.push(inArray(schema.contentDatabaseItems.id, itemIds));
127
+ }
128
+ if (documentIds.length > 0) {
129
+ rowPredicates.push(
130
+ inArray(schema.contentDatabaseItems.documentId, documentIds),
131
+ );
132
+ }
133
+
134
+ const requestedRows = await db
135
+ .select({
136
+ item: schema.contentDatabaseItems,
137
+ database: schema.contentDatabases,
138
+ document: schema.documents,
139
+ })
140
+ .from(schema.contentDatabaseItems)
141
+ .innerJoin(
142
+ schema.contentDatabases,
143
+ eq(schema.contentDatabases.id, schema.contentDatabaseItems.databaseId),
144
+ )
145
+ .innerJoin(
146
+ schema.documents,
147
+ eq(schema.documents.id, schema.contentDatabaseItems.documentId),
148
+ )
149
+ .where(
150
+ and(
151
+ eq(schema.contentDatabaseItems.databaseId, database.id),
152
+ rowPredicates.length === 1 ? rowPredicates[0] : or(...rowPredicates),
153
+ isNull(schema.contentDatabases.deletedAt),
154
+ ),
155
+ )
156
+ .orderBy(asc(schema.contentDatabaseItems.position));
157
+
158
+ const itemIdMatches = new Set(requestedRows.map((row) => row.item.id));
159
+ const documentIdMatches = new Set(
160
+ requestedRows.map((row) => row.item.documentId),
161
+ );
162
+ const missingItemIds = itemIds.filter((id) => !itemIdMatches.has(id));
163
+ const missingDocumentIds = documentIds.filter(
164
+ (id) => !documentIdMatches.has(id),
165
+ );
166
+ if (missingItemIds.length > 0 || missingDocumentIds.length > 0) {
167
+ throw new Error("All requested rows must exist in the target database.");
168
+ }
169
+
170
+ if (requestedRows.length !== requestedCount) {
171
+ throw new Error("Duplicate database row references are not allowed.");
172
+ }
173
+
174
+ const rowIds = requestedRows.map((row) => row.item.id);
175
+ if (new Set(rowIds).size !== rowIds.length) {
176
+ throw new Error("Duplicate database row references are not allowed.");
177
+ }
178
+
179
+ return { database, rows: requestedRows };
180
+ }
181
+
182
+ export async function renumberDatabaseRows(
183
+ db: ReturnType<typeof getDb>,
184
+ database: typeof schema.contentDatabases.$inferSelect,
185
+ now: string,
186
+ ) {
187
+ const rows = await db
188
+ .select()
189
+ .from(schema.contentDatabaseItems)
190
+ .where(eq(schema.contentDatabaseItems.databaseId, database.id))
191
+ .orderBy(asc(schema.contentDatabaseItems.position));
192
+ if (rows.length === 0) return;
193
+
194
+ const itemIds = rows.map((row) => row.id);
195
+ const documentIds = rows.map((row) => row.documentId);
196
+ await db
197
+ .update(schema.contentDatabaseItems)
198
+ .set({
199
+ position: positionCaseSql(
200
+ schema.contentDatabaseItems.id,
201
+ schema.contentDatabaseItems.position,
202
+ itemIds,
203
+ ),
204
+ updatedAt: now,
205
+ })
206
+ .where(
207
+ and(
208
+ eq(schema.contentDatabaseItems.databaseId, database.id),
209
+ inArray(schema.contentDatabaseItems.id, itemIds),
210
+ ),
211
+ );
212
+
213
+ await db
214
+ .update(schema.documents)
215
+ .set({
216
+ position: positionCaseSql(
217
+ schema.documents.id,
218
+ schema.documents.position,
219
+ documentIds,
220
+ ),
221
+ updatedAt: now,
222
+ })
223
+ .where(
224
+ and(
225
+ eq(schema.documents.ownerEmail, database.ownerEmail),
226
+ eq(schema.documents.parentId, database.documentId),
227
+ inArray(schema.documents.id, documentIds),
228
+ ),
229
+ );
230
+ }
@@ -285,8 +285,8 @@ export async function isSoftDeletedDatabaseDocument(documentId: string) {
285
285
  export async function getDatabaseByDocumentId(
286
286
  documentId: string,
287
287
  options: { includeDeleted?: boolean } = {},
288
+ db = getDb(),
288
289
  ) {
289
- const db = getDb();
290
290
  const clauses = [eq(schema.contentDatabases.documentId, documentId)];
291
291
  if (!options.includeDeleted) {
292
292
  clauses.push(isNull(schema.contentDatabases.deletedAt));
@@ -301,8 +301,8 @@ export async function getDatabaseByDocumentId(
301
301
  export async function getDatabaseItemByDocumentId(
302
302
  documentId: string,
303
303
  options: { includeDeleted?: boolean } = {},
304
+ db = getDb(),
304
305
  ) {
305
- const db = getDb();
306
306
  const clauses = [eq(schema.contentDatabaseItems.documentId, documentId)];
307
307
  if (!options.includeDeleted) {
308
308
  clauses.push(isNull(schema.contentDatabases.deletedAt));
@@ -332,11 +332,15 @@ export async function getDatabaseItemByDocumentId(
332
332
  export async function deleteDatabaseDataForDocument(
333
333
  documentId: string,
334
334
  ownerEmail: string,
335
+ db = getDb(),
335
336
  ) {
336
- const db = getDb();
337
- const database = await getDatabaseByDocumentId(documentId, {
338
- includeDeleted: true,
339
- });
337
+ const database = await getDatabaseByDocumentId(
338
+ documentId,
339
+ {
340
+ includeDeleted: true,
341
+ },
342
+ db,
343
+ );
340
344
  if (database) {
341
345
  const definitions = await db
342
346
  .select({ id: schema.documentPropertyDefinitions.id })
@@ -395,9 +399,13 @@ export async function deleteDatabaseDataForDocument(
395
399
  .where(eq(schema.contentDatabases.id, database.id));
396
400
  }
397
401
 
398
- const item = await getDatabaseItemByDocumentId(documentId, {
399
- includeDeleted: true,
400
- });
402
+ const item = await getDatabaseItemByDocumentId(
403
+ documentId,
404
+ {
405
+ includeDeleted: true,
406
+ },
407
+ db,
408
+ );
401
409
  if (item) {
402
410
  await db
403
411
  .delete(schema.contentDatabaseBodyHydrationQueue)
@@ -0,0 +1,26 @@
1
+ import {
2
+ getRequestOrgId,
3
+ getRequestUserEmail,
4
+ } from "@agent-native/core/server";
5
+ import { assertAccess } from "@agent-native/core/sharing";
6
+
7
+ export function getCurrentNotionOwner() {
8
+ const owner = getRequestUserEmail();
9
+ if (!owner) throw new Error("no authenticated user");
10
+ return owner;
11
+ }
12
+
13
+ export async function getNotionDocumentOwner(documentId: string) {
14
+ const userEmail = getCurrentNotionOwner();
15
+ await assertAccess("document", documentId, "editor", {
16
+ userEmail,
17
+ orgId: getRequestOrgId(),
18
+ });
19
+ return userEmail;
20
+ }
21
+
22
+ export function resolveDocumentId(args: { documentId?: string; id?: string }) {
23
+ const documentId = args.documentId || args.id;
24
+ if (!documentId) throw new Error("documentId is required");
25
+ return documentId;
26
+ }
@@ -1,21 +1,30 @@
1
1
  import { defineAction } from "@agent-native/core";
2
- import { getRequestUserEmail } from "@agent-native/core/server";
2
+ import { resolveSecret } from "@agent-native/core/server";
3
3
  import { z } from "zod";
4
4
 
5
5
  import { getNotionConnectionForOwner } from "../server/lib/notion.js";
6
+ import { getCurrentNotionOwner } from "./_notion-action-utils.js";
6
7
 
7
8
  export default defineAction({
8
9
  description: "Check Notion connection status for the current user.",
9
10
  schema: z.object({}),
10
- http: false,
11
+ http: { method: "GET" },
11
12
  run: async () => {
12
- const owner = getRequestUserEmail();
13
- if (!owner) throw new Error("no authenticated user");
13
+ const owner = getCurrentNotionOwner();
14
14
  const connection = await getNotionConnectionForOwner(owner);
15
+ const hasOAuthCredentials = Boolean(
16
+ (await resolveSecret("NOTION_CLIENT_ID")) &&
17
+ (await resolveSecret("NOTION_CLIENT_SECRET")),
18
+ );
19
+
15
20
  return {
16
21
  connected: Boolean(connection),
17
22
  workspaceName: connection?.workspaceName ?? null,
18
23
  workspaceId: connection?.workspaceId ?? null,
24
+ authUrl: null,
25
+ error:
26
+ connection || hasOAuthCredentials ? undefined : "missing_credentials",
27
+ mode: connection ? ("oauth" as const) : null,
19
28
  };
20
29
  },
21
30
  });
@@ -0,0 +1,23 @@
1
+ import { defineAction } from "@agent-native/core";
2
+ import { z } from "zod";
3
+
4
+ import { createAndLinkNotionPage } from "../server/lib/notion-sync.js";
5
+ import {
6
+ getNotionDocumentOwner,
7
+ resolveDocumentId,
8
+ } from "./_notion-action-utils.js";
9
+
10
+ export default defineAction({
11
+ description: "Create a Notion page from a Content document and link it.",
12
+ schema: z.object({
13
+ documentId: z.string().optional().describe("Document ID (required)"),
14
+ id: z.string().optional().describe("Alias for --documentId"),
15
+ parentPageIdOrUrl: z.string().optional(),
16
+ }),
17
+ http: { method: "POST" },
18
+ run: async (args) => {
19
+ const documentId = resolveDocumentId(args);
20
+ const owner = await getNotionDocumentOwner(documentId);
21
+ return createAndLinkNotionPage(owner, documentId, args.parentPageIdOrUrl);
22
+ },
23
+ });
@@ -0,0 +1,55 @@
1
+ import { defineAction } from "@agent-native/core";
2
+ import { writeAppState } from "@agent-native/core/application-state";
3
+ import { assertAccess } from "@agent-native/core/sharing";
4
+
5
+ import { getDb } from "../server/db/index.js";
6
+ import {
7
+ databaseRowBatchSchema,
8
+ renumberDatabaseRows,
9
+ resolveDatabaseRowsForBatch,
10
+ } from "./_database-row-batch.js";
11
+ import { getContentDatabaseResponse } from "./_database-utils.js";
12
+ import { deleteDocumentRecursive } from "./delete-document.js";
13
+
14
+ export default defineAction({
15
+ description:
16
+ "Delete multiple page rows from a content database in one atomic batch. Use this for two or more selected/named rows instead of looping delete-document.",
17
+ schema: databaseRowBatchSchema,
18
+ run: async (args) => {
19
+ const db = getDb();
20
+ const { database, rows } = await resolveDatabaseRowsForBatch(args);
21
+
22
+ await assertAccess("document", database.documentId, "editor");
23
+ for (const row of rows) {
24
+ await assertAccess("document", row.document.id, "admin");
25
+ }
26
+
27
+ const deletedItemIds = rows.map((row) => row.item.id);
28
+ const deletedDocumentIds = rows.map((row) => row.document.id);
29
+ const now = new Date().toISOString();
30
+
31
+ await db.transaction(async (tx) => {
32
+ for (const row of rows) {
33
+ await deleteDocumentRecursive(
34
+ tx as unknown as ReturnType<typeof getDb>,
35
+ row.document.id,
36
+ row.document.ownerEmail,
37
+ );
38
+ }
39
+ await renumberDatabaseRows(
40
+ tx as unknown as ReturnType<typeof getDb>,
41
+ database,
42
+ now,
43
+ );
44
+ });
45
+
46
+ await writeAppState("refresh-signal", { ts: Date.now() });
47
+
48
+ return {
49
+ ...(await getContentDatabaseResponse(database.id)),
50
+ deletedItemIds,
51
+ deletedDocumentIds,
52
+ deletedCount: deletedItemIds.length,
53
+ };
54
+ },
55
+ });
@@ -12,7 +12,7 @@ import {
12
12
  isContentLocalFileMode,
13
13
  } from "./_local-file-documents.js";
14
14
 
15
- async function deleteRecursive(
15
+ export async function deleteDocumentRecursive(
16
16
  db: ReturnType<typeof getDb>,
17
17
  id: string,
18
18
  ownerEmail: string,
@@ -29,11 +29,11 @@ async function deleteRecursive(
29
29
 
30
30
  const deleted: string[] = [];
31
31
  for (const child of children) {
32
- deleted.push(...(await deleteRecursive(db, child.id, ownerEmail)));
32
+ deleted.push(...(await deleteDocumentRecursive(db, child.id, ownerEmail)));
33
33
  }
34
34
 
35
35
  // Delete database membership/schema, sync links, versions, shares, then document.
36
- await deleteDatabaseDataForDocument(id, ownerEmail);
36
+ await deleteDatabaseDataForDocument(id, ownerEmail, db);
37
37
  await db
38
38
  .delete(schema.documentSyncLinks)
39
39
  .where(
@@ -86,7 +86,7 @@ export default defineAction({
86
86
  const existing = access.resource;
87
87
 
88
88
  const db = getDb();
89
- const deleted = await deleteRecursive(
89
+ const deleted = await deleteDocumentRecursive(
90
90
  db,
91
91
  id,
92
92
  existing.ownerEmail as string,
@@ -0,0 +1,16 @@
1
+ import { defineAction } from "@agent-native/core";
2
+ import { z } from "zod";
3
+
4
+ import { disconnectNotionForOwner } from "../server/lib/notion.js";
5
+ import { getCurrentNotionOwner } from "./_notion-action-utils.js";
6
+
7
+ export default defineAction({
8
+ description: "Disconnect the current user's Notion workspace.",
9
+ schema: z.object({}),
10
+ http: { method: "POST" },
11
+ run: async () => {
12
+ const owner = getCurrentNotionOwner();
13
+ const deleted = await disconnectNotionForOwner(owner);
14
+ return { success: true, deleted };
15
+ },
16
+ });
@@ -11,7 +11,7 @@ import { nanoid } from "./_property-utils.js";
11
11
 
12
12
  export default defineAction({
13
13
  description:
14
- "Duplicate a page row in a content database, including stored property values.",
14
+ "Duplicate exactly one page row in a content database, including stored property values. For two or more rows, use duplicate-database-items once instead of looping this action.",
15
15
  schema: z.object({
16
16
  itemId: z.string().optional().describe("Database item ID"),
17
17
  documentId: z.string().optional().describe("Database row document ID"),