@agent-native/core 0.96.0 → 0.97.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (450) hide show
  1. package/README.md +6 -0
  2. package/corpus/README.md +2 -2
  3. package/corpus/core/CHANGELOG.md +39 -0
  4. package/corpus/core/docs/content/audit-log.mdx +2 -1
  5. package/corpus/core/docs/content/automations.mdx +7 -7
  6. package/corpus/core/docs/content/creating-templates.mdx +1 -1
  7. package/corpus/core/docs/content/internationalization.mdx +2 -1
  8. package/corpus/core/docs/content/locales/ar-SA/audit-log.mdx +2 -1
  9. package/corpus/core/docs/content/locales/ar-SA/automations.mdx +7 -7
  10. package/corpus/core/docs/content/locales/ar-SA/getting-started.mdx +7 -1
  11. package/corpus/core/docs/content/locales/ar-SA/internationalization.mdx +1 -1
  12. package/corpus/core/docs/content/locales/ar-SA/package-lifecycle.mdx +19 -0
  13. package/corpus/core/docs/content/locales/ar-SA/sandbox-adapters.mdx +18 -7
  14. package/corpus/core/docs/content/locales/ar-SA/security.mdx +8 -0
  15. package/corpus/core/docs/content/locales/de-DE/audit-log.mdx +2 -1
  16. package/corpus/core/docs/content/locales/de-DE/automations.mdx +7 -7
  17. package/corpus/core/docs/content/locales/de-DE/getting-started.mdx +7 -1
  18. package/corpus/core/docs/content/locales/de-DE/internationalization.mdx +1 -1
  19. package/corpus/core/docs/content/locales/de-DE/package-lifecycle.mdx +22 -0
  20. package/corpus/core/docs/content/locales/de-DE/sandbox-adapters.mdx +18 -7
  21. package/corpus/core/docs/content/locales/de-DE/security.mdx +8 -0
  22. package/corpus/core/docs/content/locales/es-ES/audit-log.mdx +2 -1
  23. package/corpus/core/docs/content/locales/es-ES/automations.mdx +7 -7
  24. package/corpus/core/docs/content/locales/es-ES/getting-started.mdx +7 -1
  25. package/corpus/core/docs/content/locales/es-ES/internationalization.mdx +1 -1
  26. package/corpus/core/docs/content/locales/es-ES/package-lifecycle.mdx +22 -0
  27. package/corpus/core/docs/content/locales/es-ES/sandbox-adapters.mdx +18 -7
  28. package/corpus/core/docs/content/locales/es-ES/security.mdx +8 -0
  29. package/corpus/core/docs/content/locales/fr-FR/audit-log.mdx +2 -1
  30. package/corpus/core/docs/content/locales/fr-FR/automations.mdx +7 -7
  31. package/corpus/core/docs/content/locales/fr-FR/getting-started.mdx +7 -1
  32. package/corpus/core/docs/content/locales/fr-FR/internationalization.mdx +1 -1
  33. package/corpus/core/docs/content/locales/fr-FR/package-lifecycle.mdx +21 -0
  34. package/corpus/core/docs/content/locales/fr-FR/sandbox-adapters.mdx +19 -8
  35. package/corpus/core/docs/content/locales/fr-FR/security.mdx +8 -0
  36. package/corpus/core/docs/content/locales/hi-IN/audit-log.mdx +2 -1
  37. package/corpus/core/docs/content/locales/hi-IN/automations.mdx +7 -7
  38. package/corpus/core/docs/content/locales/hi-IN/getting-started.mdx +7 -1
  39. package/corpus/core/docs/content/locales/hi-IN/internationalization.mdx +1 -1
  40. package/corpus/core/docs/content/locales/hi-IN/package-lifecycle.mdx +20 -0
  41. package/corpus/core/docs/content/locales/hi-IN/sandbox-adapters.mdx +18 -7
  42. package/corpus/core/docs/content/locales/hi-IN/security.mdx +8 -0
  43. package/corpus/core/docs/content/locales/ja-JP/audit-log.mdx +2 -1
  44. package/corpus/core/docs/content/locales/ja-JP/automations.mdx +7 -7
  45. package/corpus/core/docs/content/locales/ja-JP/getting-started.mdx +7 -1
  46. package/corpus/core/docs/content/locales/ja-JP/internationalization.mdx +1 -1
  47. package/corpus/core/docs/content/locales/ja-JP/package-lifecycle.mdx +21 -0
  48. package/corpus/core/docs/content/locales/ja-JP/sandbox-adapters.mdx +17 -6
  49. package/corpus/core/docs/content/locales/ja-JP/security.mdx +8 -0
  50. package/corpus/core/docs/content/locales/ko-KR/audit-log.mdx +2 -1
  51. package/corpus/core/docs/content/locales/ko-KR/automations.mdx +7 -7
  52. package/corpus/core/docs/content/locales/ko-KR/getting-started.mdx +7 -1
  53. package/corpus/core/docs/content/locales/ko-KR/internationalization.mdx +1 -1
  54. package/corpus/core/docs/content/locales/ko-KR/package-lifecycle.mdx +20 -0
  55. package/corpus/core/docs/content/locales/ko-KR/sandbox-adapters.mdx +17 -6
  56. package/corpus/core/docs/content/locales/ko-KR/security.mdx +8 -0
  57. package/corpus/core/docs/content/locales/pt-BR/audit-log.mdx +2 -1
  58. package/corpus/core/docs/content/locales/pt-BR/automations.mdx +7 -7
  59. package/corpus/core/docs/content/locales/pt-BR/getting-started.mdx +7 -1
  60. package/corpus/core/docs/content/locales/pt-BR/internationalization.mdx +1 -1
  61. package/corpus/core/docs/content/locales/pt-BR/package-lifecycle.mdx +21 -0
  62. package/corpus/core/docs/content/locales/pt-BR/sandbox-adapters.mdx +18 -7
  63. package/corpus/core/docs/content/locales/pt-BR/security.mdx +8 -0
  64. package/corpus/core/docs/content/locales/zh-CN/audit-log.mdx +2 -1
  65. package/corpus/core/docs/content/locales/zh-CN/automations.mdx +7 -7
  66. package/corpus/core/docs/content/locales/zh-CN/getting-started.mdx +6 -4
  67. package/corpus/core/docs/content/locales/zh-CN/internationalization.mdx +1 -1
  68. package/corpus/core/docs/content/locales/zh-CN/package-lifecycle.mdx +19 -0
  69. package/corpus/core/docs/content/locales/zh-CN/sandbox-adapters.mdx +17 -6
  70. package/corpus/core/docs/content/locales/zh-CN/security.mdx +8 -0
  71. package/corpus/core/docs/content/locales/zh-TW/audit-log.mdx +2 -1
  72. package/corpus/core/docs/content/locales/zh-TW/automations.mdx +7 -7
  73. package/corpus/core/docs/content/locales/zh-TW/getting-started.mdx +6 -4
  74. package/corpus/core/docs/content/locales/zh-TW/internationalization.mdx +1 -1
  75. package/corpus/core/docs/content/locales/zh-TW/package-lifecycle.mdx +19 -0
  76. package/corpus/core/docs/content/locales/zh-TW/sandbox-adapters.mdx +18 -7
  77. package/corpus/core/docs/content/locales/zh-TW/security.mdx +8 -0
  78. package/corpus/core/docs/content/package-lifecycle.mdx +51 -0
  79. package/corpus/core/docs/content/sandbox-adapters.mdx +16 -5
  80. package/corpus/core/package.json +9 -2
  81. package/corpus/core/src/a2a/auth-policy.ts +33 -0
  82. package/corpus/core/src/agent/durable-background.ts +15 -7
  83. package/corpus/core/src/agent/run-store.ts +13 -4
  84. package/corpus/core/src/audit/actions/export-audit-events.ts +162 -0
  85. package/corpus/core/src/audit/store.ts +8 -3
  86. package/corpus/core/src/audit/types.ts +3 -0
  87. package/corpus/core/src/cli/doctor.ts +396 -0
  88. package/corpus/core/src/cli/index.ts +56 -0
  89. package/corpus/core/src/cli/info.ts +3 -3
  90. package/corpus/core/src/cli/package-lifecycle.ts +821 -0
  91. package/corpus/core/src/client/agent-chat-adapter.ts +9 -9
  92. package/corpus/core/src/guards/db-tool-scoping.ts +129 -0
  93. package/corpus/core/src/guards/index.ts +23 -0
  94. package/corpus/core/src/guards/no-drizzle-push.ts +116 -0
  95. package/corpus/core/src/guards/no-env-credentials.ts +229 -0
  96. package/corpus/core/src/guards/no-env-mutation.ts +114 -0
  97. package/corpus/core/src/guards/no-localhost-fallback.ts +124 -0
  98. package/corpus/core/src/guards/no-unscoped-credentials.ts +227 -0
  99. package/corpus/core/src/guards/no-unscoped-queries.ts +834 -0
  100. package/corpus/core/src/guards/scan-utils.ts +105 -0
  101. package/corpus/core/src/guards/types.ts +30 -0
  102. package/corpus/core/src/org/accept-pending.ts +9 -1
  103. package/corpus/core/src/org/migrations.ts +41 -0
  104. package/corpus/core/src/package-lifecycle/index.ts +1 -0
  105. package/corpus/core/src/package-lifecycle/manifest.ts +120 -0
  106. package/corpus/core/src/provider-api/custom-registry.ts +56 -0
  107. package/corpus/core/src/provider-api/index.ts +2 -0
  108. package/corpus/core/src/secrets/storage.ts +47 -27
  109. package/corpus/core/src/server/action-discovery.ts +4 -0
  110. package/corpus/core/src/server/agent-chat-plugin.ts +54 -12
  111. package/corpus/core/src/server/core-routes-plugin.ts +30 -14
  112. package/corpus/core/src/server/csrf.ts +24 -5
  113. package/corpus/core/src/server/framework-request-handler.ts +34 -0
  114. package/corpus/core/src/server/google-realtime-session.ts +1 -36
  115. package/corpus/core/src/server/poll.ts +24 -2
  116. package/corpus/core/src/server/realtime-voice.ts +9 -0
  117. package/corpus/core/src/server/request-origin.ts +63 -0
  118. package/corpus/core/src/server/transcribe-voice.ts +1 -50
  119. package/corpus/core/src/templates/default/package.json +2 -2
  120. package/corpus/core/src/templates/headless/package.json +0 -1
  121. package/corpus/core/src/templates/workspace-core/.agents/skills/audit-log/SKILL.md +3 -0
  122. package/corpus/core/src/templates/workspace-core/.agents/skills/automations/SKILL.md +1 -1
  123. package/corpus/core/src/templates/workspace-core/package.json +0 -1
  124. package/corpus/core/src/templates/workspace-root/package.json +0 -1
  125. package/corpus/core/src/triggers/actions.ts +11 -3
  126. package/corpus/core/src/triggers/types.ts +7 -1
  127. package/corpus/templates/analytics/actions/compose-dashboard.ts +65 -37
  128. package/corpus/templates/analytics/actions/mutate-dashboard.ts +73 -24
  129. package/corpus/templates/analytics/actions/reorder-dashboard-panels.ts +16 -13
  130. package/corpus/templates/analytics/actions/update-dashboard.ts +53 -42
  131. package/corpus/templates/analytics/changelog/2026-07-10-dashboard-edits-from-the-agent-and-the-ui-at-the-same-time-n.md +6 -0
  132. package/corpus/templates/analytics/changelog/2026-07-10-timed-out-bigquery-jobs-are-now-cancelled-so-they-stop-consu.md +6 -0
  133. package/corpus/templates/analytics/package.json +1 -2
  134. package/corpus/templates/analytics/server/lib/bigquery.ts +3 -2
  135. package/corpus/templates/analytics/server/lib/dashboards-store.ts +154 -11
  136. package/corpus/templates/assets/package.json +1 -2
  137. package/corpus/templates/brain/package.json +1 -2
  138. package/corpus/templates/calendar/package.json +1 -2
  139. package/corpus/templates/chat/package.json +1 -2
  140. package/corpus/templates/clips/changelog/2026-07-10-atomic-view-tracking.md +6 -0
  141. package/corpus/templates/clips/chrome-extension/package.json +3 -2
  142. package/corpus/templates/clips/desktop/package.json +6 -4
  143. package/corpus/templates/clips/desktop/src/lib/recorder.ts +26 -13
  144. package/corpus/templates/clips/desktop/src/lib/voice-dictation.ts +4 -1
  145. package/corpus/templates/clips/package.json +1 -2
  146. package/corpus/templates/clips/server/db/schema.ts +29 -17
  147. package/corpus/templates/clips/server/plugins/db.ts +8 -0
  148. package/corpus/templates/clips/server/routes/api/view-event.post.ts +260 -105
  149. package/corpus/templates/content/.agents/skills/notion-integration/SKILL.md +16 -0
  150. package/corpus/templates/content/AGENTS.md +72 -62
  151. package/corpus/templates/content/actions/_content-database-source-adapters.ts +84 -0
  152. package/corpus/templates/content/actions/_database-source-utils.ts +206 -96
  153. package/corpus/templates/content/actions/_notion-database-source-adapter.ts +216 -0
  154. package/corpus/templates/content/actions/_position-utils.ts +76 -0
  155. package/corpus/templates/content/actions/_property-utils.ts +31 -20
  156. package/corpus/templates/content/actions/add-database-item.ts +52 -39
  157. package/corpus/templates/content/actions/attach-content-database-source.ts +95 -11
  158. package/corpus/templates/content/actions/change-content-database-source-role.ts +24 -1
  159. package/corpus/templates/content/actions/configure-document-property.ts +36 -27
  160. package/corpus/templates/content/actions/create-content-database.ts +40 -30
  161. package/corpus/templates/content/actions/create-document.ts +39 -32
  162. package/corpus/templates/content/actions/duplicate-document-property.ts +37 -28
  163. package/corpus/templates/content/actions/list-notion-database-sources.ts +80 -0
  164. package/corpus/templates/content/actions/move-document.ts +64 -48
  165. package/corpus/templates/content/actions/refresh-content-database-source.ts +42 -3
  166. package/corpus/templates/content/actions/share-local-file-document.ts +36 -27
  167. package/corpus/templates/content/actions/suggest-source-join-key.ts +39 -16
  168. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +89 -23
  169. package/corpus/templates/content/app/components/editor/database/settings.tsx +1 -1
  170. package/corpus/templates/content/app/hooks/use-content-database.ts +18 -1
  171. package/corpus/templates/content/app/i18n/zh-TW.ts +4 -0
  172. package/corpus/templates/content/app/i18n-data.ts +40 -0
  173. package/corpus/templates/content/changelog/2026-07-10-failed-row-creation-and-source-attach-now-show-an-error-inst.md +6 -0
  174. package/corpus/templates/content/changelog/2026-07-10-items-added-at-the-same-time-no-longer-end-up-with-identical.md +6 -0
  175. package/corpus/templates/content/changelog/2026-07-10-notion-databases-can-add-read-only-details-to-content-tables.md +6 -0
  176. package/corpus/templates/content/package.json +1 -2
  177. package/corpus/templates/content/parity/matrix.md +25 -25
  178. package/corpus/templates/content/parity/matrix.ts +1 -0
  179. package/corpus/templates/content/server/routes/api/documents/[id]/move.patch.ts +43 -26
  180. package/corpus/templates/content/shared/api.ts +16 -1
  181. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +8 -4
  182. package/corpus/templates/design/AGENTS.md +12 -2
  183. package/corpus/templates/design/DEVELOPING.md +10 -6
  184. package/corpus/templates/design/actions/apply-visual-edit.ts +191 -6
  185. package/corpus/templates/design/actions/duplicate-design.ts +31 -25
  186. package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +5 -1
  187. package/corpus/templates/design/changelog/2026-07-10-duplicating-a-design-can-no-longer-produce-a-copy-with-missi.md +6 -0
  188. package/corpus/templates/design/changelog/2026-07-10-local-visual-edits-can-now-save-safe-leaf-text-class-and.md +6 -0
  189. package/corpus/templates/design/package.json +1 -1
  190. package/corpus/templates/design/shared/local-jsx-visual-edit.ts +388 -0
  191. package/corpus/templates/dispatch/package.json +1 -2
  192. package/corpus/templates/forms/actions/patch-form-fields.ts +82 -44
  193. package/corpus/templates/forms/changelog/2026-07-10-simultaneous-edits-to-different-form-fields-no-longer-overwr.md +6 -0
  194. package/corpus/templates/forms/package.json +1 -2
  195. package/corpus/templates/macros/package.json +1 -2
  196. package/corpus/templates/mail/app/components/email/EmailThread.tsx +3 -1
  197. package/corpus/templates/mail/changelog/2026-07-10-fixed-calendar-rsvp-buttons-in-emails-firing-duplicate-respo.md +6 -0
  198. package/corpus/templates/mail/package.json +1 -2
  199. package/corpus/templates/plan/actions/restore-plan-version.ts +126 -96
  200. package/corpus/templates/plan/changelog/2026-07-10-restoring-a-plan-version-can-no-longer-leave-a-plan-half-res.md +6 -0
  201. package/corpus/templates/plan/package.json +1 -2
  202. package/corpus/templates/plan/server/plans.ts +9 -2
  203. package/corpus/templates/slides/actions/list-decks.ts +28 -0
  204. package/corpus/templates/slides/app/components/deck/MermaidRenderer.tsx +41 -26
  205. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +4 -8
  206. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +2 -4
  207. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +4 -8
  208. package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +5 -12
  209. package/corpus/templates/slides/app/components/editor/HistoryPanel.tsx +3 -6
  210. package/corpus/templates/slides/app/components/editor/ImageDropPromptPopover.tsx +3 -6
  211. package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +2 -5
  212. package/corpus/templates/slides/app/context/DeckContext.tsx +47 -4
  213. package/corpus/templates/slides/app/pages/DeckEditor.tsx +11 -30
  214. package/corpus/templates/slides/app/pages/Index.tsx +2 -3
  215. package/corpus/templates/slides/app/root.tsx +0 -5
  216. package/corpus/templates/slides/changelog/2026-07-10-deck-lists-load-much-faster-and-no-longer-re-download-slide-.md +6 -0
  217. package/corpus/templates/slides/package.json +1 -2
  218. package/dist/a2a/auth-policy.d.ts +19 -0
  219. package/dist/a2a/auth-policy.d.ts.map +1 -1
  220. package/dist/a2a/auth-policy.js +32 -0
  221. package/dist/a2a/auth-policy.js.map +1 -1
  222. package/dist/agent/durable-background.d.ts +8 -5
  223. package/dist/agent/durable-background.d.ts.map +1 -1
  224. package/dist/agent/durable-background.js +15 -8
  225. package/dist/agent/durable-background.js.map +1 -1
  226. package/dist/agent/run-store.d.ts.map +1 -1
  227. package/dist/agent/run-store.js +9 -4
  228. package/dist/agent/run-store.js.map +1 -1
  229. package/dist/audit/actions/export-audit-events.d.ts +27 -0
  230. package/dist/audit/actions/export-audit-events.d.ts.map +1 -0
  231. package/dist/audit/actions/export-audit-events.js +144 -0
  232. package/dist/audit/actions/export-audit-events.js.map +1 -0
  233. package/dist/audit/store.d.ts +1 -0
  234. package/dist/audit/store.d.ts.map +1 -1
  235. package/dist/audit/store.js +8 -3
  236. package/dist/audit/store.js.map +1 -1
  237. package/dist/audit/types.d.ts +3 -0
  238. package/dist/audit/types.d.ts.map +1 -1
  239. package/dist/audit/types.js.map +1 -1
  240. package/dist/cli/doctor.d.ts +83 -0
  241. package/dist/cli/doctor.d.ts.map +1 -0
  242. package/dist/cli/doctor.js +277 -0
  243. package/dist/cli/doctor.js.map +1 -0
  244. package/dist/cli/index.js +50 -0
  245. package/dist/cli/index.js.map +1 -1
  246. package/dist/cli/info.js +3 -3
  247. package/dist/cli/info.js.map +1 -1
  248. package/dist/cli/package-lifecycle.d.ts +50 -0
  249. package/dist/cli/package-lifecycle.d.ts.map +1 -0
  250. package/dist/cli/package-lifecycle.js +560 -0
  251. package/dist/cli/package-lifecycle.js.map +1 -0
  252. package/dist/client/agent-chat-adapter.js +7 -3
  253. package/dist/client/agent-chat-adapter.js.map +1 -1
  254. package/dist/collab/struct-routes.d.ts +1 -1
  255. package/dist/guards/db-tool-scoping.d.ts +38 -0
  256. package/dist/guards/db-tool-scoping.d.ts.map +1 -0
  257. package/dist/guards/db-tool-scoping.js +114 -0
  258. package/dist/guards/db-tool-scoping.js.map +1 -0
  259. package/dist/guards/index.d.ts +23 -0
  260. package/dist/guards/index.d.ts.map +1 -0
  261. package/dist/guards/index.js +19 -0
  262. package/dist/guards/index.js.map +1 -0
  263. package/dist/guards/no-drizzle-push.d.ts +14 -0
  264. package/dist/guards/no-drizzle-push.d.ts.map +1 -0
  265. package/dist/guards/no-drizzle-push.js +97 -0
  266. package/dist/guards/no-drizzle-push.js.map +1 -0
  267. package/dist/guards/no-env-credentials.d.ts +36 -0
  268. package/dist/guards/no-env-credentials.d.ts.map +1 -0
  269. package/dist/guards/no-env-credentials.js +204 -0
  270. package/dist/guards/no-env-credentials.js.map +1 -0
  271. package/dist/guards/no-env-mutation.d.ts +23 -0
  272. package/dist/guards/no-env-mutation.d.ts.map +1 -0
  273. package/dist/guards/no-env-mutation.js +90 -0
  274. package/dist/guards/no-env-mutation.js.map +1 -0
  275. package/dist/guards/no-localhost-fallback.d.ts +30 -0
  276. package/dist/guards/no-localhost-fallback.d.ts.map +1 -0
  277. package/dist/guards/no-localhost-fallback.js +105 -0
  278. package/dist/guards/no-localhost-fallback.js.map +1 -0
  279. package/dist/guards/no-unscoped-credentials.d.ts +28 -0
  280. package/dist/guards/no-unscoped-credentials.d.ts.map +1 -0
  281. package/dist/guards/no-unscoped-credentials.js +199 -0
  282. package/dist/guards/no-unscoped-credentials.js.map +1 -0
  283. package/dist/guards/no-unscoped-queries.d.ts +32 -0
  284. package/dist/guards/no-unscoped-queries.d.ts.map +1 -0
  285. package/dist/guards/no-unscoped-queries.js +720 -0
  286. package/dist/guards/no-unscoped-queries.js.map +1 -0
  287. package/dist/guards/scan-utils.d.ts +28 -0
  288. package/dist/guards/scan-utils.d.ts.map +1 -0
  289. package/dist/guards/scan-utils.js +92 -0
  290. package/dist/guards/scan-utils.js.map +1 -0
  291. package/dist/guards/types.d.ts +28 -0
  292. package/dist/guards/types.d.ts.map +1 -0
  293. package/dist/guards/types.js +11 -0
  294. package/dist/guards/types.js.map +1 -0
  295. package/dist/org/accept-pending.d.ts.map +1 -1
  296. package/dist/org/accept-pending.js +9 -1
  297. package/dist/org/accept-pending.js.map +1 -1
  298. package/dist/org/migrations.d.ts +7 -2
  299. package/dist/org/migrations.d.ts.map +1 -1
  300. package/dist/org/migrations.js +41 -0
  301. package/dist/org/migrations.js.map +1 -1
  302. package/dist/package-lifecycle/index.d.ts +2 -0
  303. package/dist/package-lifecycle/index.d.ts.map +1 -0
  304. package/dist/package-lifecycle/index.js +2 -0
  305. package/dist/package-lifecycle/index.js.map +1 -0
  306. package/dist/package-lifecycle/manifest.d.ts +24 -0
  307. package/dist/package-lifecycle/manifest.d.ts.map +1 -0
  308. package/dist/package-lifecycle/manifest.js +81 -0
  309. package/dist/package-lifecycle/manifest.js.map +1 -0
  310. package/dist/progress/routes.d.ts +1 -1
  311. package/dist/provider-api/custom-registry.d.ts +32 -1
  312. package/dist/provider-api/custom-registry.d.ts.map +1 -1
  313. package/dist/provider-api/custom-registry.js +41 -1
  314. package/dist/provider-api/custom-registry.js.map +1 -1
  315. package/dist/provider-api/index.d.ts +1 -1
  316. package/dist/provider-api/index.d.ts.map +1 -1
  317. package/dist/provider-api/index.js +1 -1
  318. package/dist/provider-api/index.js.map +1 -1
  319. package/dist/secrets/storage.d.ts.map +1 -1
  320. package/dist/secrets/storage.js +45 -27
  321. package/dist/secrets/storage.js.map +1 -1
  322. package/dist/server/action-discovery.d.ts.map +1 -1
  323. package/dist/server/action-discovery.js +4 -0
  324. package/dist/server/action-discovery.js.map +1 -1
  325. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  326. package/dist/server/agent-chat-plugin.js +47 -13
  327. package/dist/server/agent-chat-plugin.js.map +1 -1
  328. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  329. package/dist/server/core-routes-plugin.js +23 -12
  330. package/dist/server/core-routes-plugin.js.map +1 -1
  331. package/dist/server/csrf.d.ts.map +1 -1
  332. package/dist/server/csrf.js +18 -5
  333. package/dist/server/csrf.js.map +1 -1
  334. package/dist/server/framework-request-handler.d.ts.map +1 -1
  335. package/dist/server/framework-request-handler.js +34 -0
  336. package/dist/server/framework-request-handler.js.map +1 -1
  337. package/dist/server/google-realtime-session.d.ts.map +1 -1
  338. package/dist/server/google-realtime-session.js +2 -34
  339. package/dist/server/google-realtime-session.js.map +1 -1
  340. package/dist/server/poll.d.ts.map +1 -1
  341. package/dist/server/poll.js +24 -2
  342. package/dist/server/poll.js.map +1 -1
  343. package/dist/server/realtime-voice.d.ts.map +1 -1
  344. package/dist/server/realtime-voice.js +9 -0
  345. package/dist/server/realtime-voice.js.map +1 -1
  346. package/dist/server/request-origin.d.ts +10 -0
  347. package/dist/server/request-origin.d.ts.map +1 -0
  348. package/dist/server/request-origin.js +60 -0
  349. package/dist/server/request-origin.js.map +1 -0
  350. package/dist/server/transcribe-voice.d.ts.map +1 -1
  351. package/dist/server/transcribe-voice.js +2 -48
  352. package/dist/server/transcribe-voice.js.map +1 -1
  353. package/dist/templates/default/package.json +2 -2
  354. package/dist/templates/headless/package.json +0 -1
  355. package/dist/templates/workspace-core/.agents/skills/audit-log/SKILL.md +3 -0
  356. package/dist/templates/workspace-core/.agents/skills/automations/SKILL.md +1 -1
  357. package/dist/templates/workspace-core/package.json +0 -1
  358. package/dist/templates/workspace-root/package.json +0 -1
  359. package/dist/triggers/actions.d.ts.map +1 -1
  360. package/dist/triggers/actions.js +8 -3
  361. package/dist/triggers/actions.js.map +1 -1
  362. package/dist/triggers/types.d.ts +7 -1
  363. package/dist/triggers/types.d.ts.map +1 -1
  364. package/dist/triggers/types.js.map +1 -1
  365. package/docs/content/audit-log.mdx +2 -1
  366. package/docs/content/automations.mdx +7 -7
  367. package/docs/content/creating-templates.mdx +1 -1
  368. package/docs/content/internationalization.mdx +2 -1
  369. package/docs/content/locales/ar-SA/audit-log.mdx +2 -1
  370. package/docs/content/locales/ar-SA/automations.mdx +7 -7
  371. package/docs/content/locales/ar-SA/getting-started.mdx +7 -1
  372. package/docs/content/locales/ar-SA/internationalization.mdx +1 -1
  373. package/docs/content/locales/ar-SA/package-lifecycle.mdx +19 -0
  374. package/docs/content/locales/ar-SA/sandbox-adapters.mdx +18 -7
  375. package/docs/content/locales/ar-SA/security.mdx +8 -0
  376. package/docs/content/locales/de-DE/audit-log.mdx +2 -1
  377. package/docs/content/locales/de-DE/automations.mdx +7 -7
  378. package/docs/content/locales/de-DE/getting-started.mdx +7 -1
  379. package/docs/content/locales/de-DE/internationalization.mdx +1 -1
  380. package/docs/content/locales/de-DE/package-lifecycle.mdx +22 -0
  381. package/docs/content/locales/de-DE/sandbox-adapters.mdx +18 -7
  382. package/docs/content/locales/de-DE/security.mdx +8 -0
  383. package/docs/content/locales/es-ES/audit-log.mdx +2 -1
  384. package/docs/content/locales/es-ES/automations.mdx +7 -7
  385. package/docs/content/locales/es-ES/getting-started.mdx +7 -1
  386. package/docs/content/locales/es-ES/internationalization.mdx +1 -1
  387. package/docs/content/locales/es-ES/package-lifecycle.mdx +22 -0
  388. package/docs/content/locales/es-ES/sandbox-adapters.mdx +18 -7
  389. package/docs/content/locales/es-ES/security.mdx +8 -0
  390. package/docs/content/locales/fr-FR/audit-log.mdx +2 -1
  391. package/docs/content/locales/fr-FR/automations.mdx +7 -7
  392. package/docs/content/locales/fr-FR/getting-started.mdx +7 -1
  393. package/docs/content/locales/fr-FR/internationalization.mdx +1 -1
  394. package/docs/content/locales/fr-FR/package-lifecycle.mdx +21 -0
  395. package/docs/content/locales/fr-FR/sandbox-adapters.mdx +19 -8
  396. package/docs/content/locales/fr-FR/security.mdx +8 -0
  397. package/docs/content/locales/hi-IN/audit-log.mdx +2 -1
  398. package/docs/content/locales/hi-IN/automations.mdx +7 -7
  399. package/docs/content/locales/hi-IN/getting-started.mdx +7 -1
  400. package/docs/content/locales/hi-IN/internationalization.mdx +1 -1
  401. package/docs/content/locales/hi-IN/package-lifecycle.mdx +20 -0
  402. package/docs/content/locales/hi-IN/sandbox-adapters.mdx +18 -7
  403. package/docs/content/locales/hi-IN/security.mdx +8 -0
  404. package/docs/content/locales/ja-JP/audit-log.mdx +2 -1
  405. package/docs/content/locales/ja-JP/automations.mdx +7 -7
  406. package/docs/content/locales/ja-JP/getting-started.mdx +7 -1
  407. package/docs/content/locales/ja-JP/internationalization.mdx +1 -1
  408. package/docs/content/locales/ja-JP/package-lifecycle.mdx +21 -0
  409. package/docs/content/locales/ja-JP/sandbox-adapters.mdx +17 -6
  410. package/docs/content/locales/ja-JP/security.mdx +8 -0
  411. package/docs/content/locales/ko-KR/audit-log.mdx +2 -1
  412. package/docs/content/locales/ko-KR/automations.mdx +7 -7
  413. package/docs/content/locales/ko-KR/getting-started.mdx +7 -1
  414. package/docs/content/locales/ko-KR/internationalization.mdx +1 -1
  415. package/docs/content/locales/ko-KR/package-lifecycle.mdx +20 -0
  416. package/docs/content/locales/ko-KR/sandbox-adapters.mdx +17 -6
  417. package/docs/content/locales/ko-KR/security.mdx +8 -0
  418. package/docs/content/locales/pt-BR/audit-log.mdx +2 -1
  419. package/docs/content/locales/pt-BR/automations.mdx +7 -7
  420. package/docs/content/locales/pt-BR/getting-started.mdx +7 -1
  421. package/docs/content/locales/pt-BR/internationalization.mdx +1 -1
  422. package/docs/content/locales/pt-BR/package-lifecycle.mdx +21 -0
  423. package/docs/content/locales/pt-BR/sandbox-adapters.mdx +18 -7
  424. package/docs/content/locales/pt-BR/security.mdx +8 -0
  425. package/docs/content/locales/zh-CN/audit-log.mdx +2 -1
  426. package/docs/content/locales/zh-CN/automations.mdx +7 -7
  427. package/docs/content/locales/zh-CN/getting-started.mdx +6 -4
  428. package/docs/content/locales/zh-CN/internationalization.mdx +1 -1
  429. package/docs/content/locales/zh-CN/package-lifecycle.mdx +19 -0
  430. package/docs/content/locales/zh-CN/sandbox-adapters.mdx +17 -6
  431. package/docs/content/locales/zh-CN/security.mdx +8 -0
  432. package/docs/content/locales/zh-TW/audit-log.mdx +2 -1
  433. package/docs/content/locales/zh-TW/automations.mdx +7 -7
  434. package/docs/content/locales/zh-TW/getting-started.mdx +6 -4
  435. package/docs/content/locales/zh-TW/internationalization.mdx +1 -1
  436. package/docs/content/locales/zh-TW/package-lifecycle.mdx +19 -0
  437. package/docs/content/locales/zh-TW/sandbox-adapters.mdx +18 -7
  438. package/docs/content/locales/zh-TW/security.mdx +8 -0
  439. package/docs/content/package-lifecycle.mdx +51 -0
  440. package/docs/content/sandbox-adapters.mdx +16 -5
  441. package/package.json +10 -3
  442. package/src/templates/default/package.json +2 -2
  443. package/src/templates/headless/package.json +0 -1
  444. package/src/templates/workspace-core/.agents/skills/audit-log/SKILL.md +3 -0
  445. package/src/templates/workspace-core/.agents/skills/automations/SKILL.md +1 -1
  446. package/src/templates/workspace-core/package.json +0 -1
  447. package/src/templates/workspace-root/package.json +0 -1
  448. package/corpus/templates/slides/app/components/ui/toast.tsx +0 -1
  449. package/corpus/templates/slides/app/components/ui/toaster.tsx +0 -1
  450. package/corpus/templates/slides/app/hooks/use-toast.ts +0 -1
@@ -10,6 +10,10 @@ import {
10
10
  serializePropertyOptions,
11
11
  type DocumentPropertyType,
12
12
  } from "../shared/properties.js";
13
+ import {
14
+ propertyDefinitionsPositionScope,
15
+ withPositionLock,
16
+ } from "./_position-utils.js";
13
17
  import {
14
18
  listPropertiesForDocument,
15
19
  nanoid,
@@ -45,21 +49,6 @@ export default defineAction({
45
49
  );
46
50
  if (!definition) throw new Error(`Property "${propertyId}" not found`);
47
51
 
48
- const [maxPos] = await db
49
- .select({
50
- max: sql<number>`COALESCE(MAX(position), -1)`,
51
- })
52
- .from(schema.documentPropertyDefinitions)
53
- .where(
54
- and(
55
- eq(
56
- schema.documentPropertyDefinitions.ownerEmail,
57
- document.ownerEmail,
58
- ),
59
- eq(schema.documentPropertyDefinitions.databaseId, database.id),
60
- ),
61
- );
62
-
63
52
  const now = new Date().toISOString();
64
53
  const newPropertyId = nanoid();
65
54
  const isBlocks = isBlocksPropertyType(
@@ -71,19 +60,39 @@ export default defineAction({
71
60
  ? serializePropertyOptions({ blocks: { primary: false } })
72
61
  : definition.optionsJson;
73
62
 
74
- await db.insert(schema.documentPropertyDefinitions).values({
75
- id: newPropertyId,
76
- ownerEmail: definition.ownerEmail,
77
- orgId: definition.orgId,
78
- databaseId: database.id,
79
- name: `${definition.name} copy`,
80
- type: definition.type,
81
- visibility: definition.visibility,
82
- optionsJson,
83
- position: (maxPos?.max ?? -1) + 1,
84
- createdAt: now,
85
- updatedAt: now,
86
- });
63
+ await withPositionLock(
64
+ propertyDefinitionsPositionScope(database.id),
65
+ async () => {
66
+ const [maxPos] = await db
67
+ .select({
68
+ max: sql<number>`COALESCE(MAX(position), -1)`,
69
+ })
70
+ .from(schema.documentPropertyDefinitions)
71
+ .where(
72
+ and(
73
+ eq(
74
+ schema.documentPropertyDefinitions.ownerEmail,
75
+ document.ownerEmail,
76
+ ),
77
+ eq(schema.documentPropertyDefinitions.databaseId, database.id),
78
+ ),
79
+ );
80
+
81
+ await db.insert(schema.documentPropertyDefinitions).values({
82
+ id: newPropertyId,
83
+ ownerEmail: definition.ownerEmail,
84
+ orgId: definition.orgId,
85
+ databaseId: database.id,
86
+ name: `${definition.name} copy`,
87
+ type: definition.type,
88
+ visibility: definition.visibility,
89
+ optionsJson,
90
+ position: (maxPos?.max ?? -1) + 1,
91
+ createdAt: now,
92
+ updatedAt: now,
93
+ });
94
+ },
95
+ );
87
96
 
88
97
  // Blocks fields don't use document_property_values; a duplicate starts empty.
89
98
  if (!isBlocks) {
@@ -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
+ import {
6
+ getNotionConnectionForOwner,
7
+ notionFetch,
8
+ } from "../server/lib/notion.js";
9
+ import type { NotionDatabaseSourcesResponse } from "../shared/api.js";
10
+
11
+ function plainText(value: unknown) {
12
+ return Array.isArray(value)
13
+ ? value
14
+ .map((part) =>
15
+ typeof part === "object" && part && "plain_text" in part
16
+ ? String((part as { plain_text?: unknown }).plain_text ?? "")
17
+ : "",
18
+ )
19
+ .join("")
20
+ : "";
21
+ }
22
+
23
+ export default defineAction({
24
+ description:
25
+ "List Notion data sources visible to the current user's connected Notion workspace so one can be attached read-only to a Content database.",
26
+ schema: z.object({
27
+ query: z.string().trim().max(200).optional(),
28
+ limit: z.coerce.number().int().min(1).max(100).default(50),
29
+ cursor: z.string().trim().min(1).optional(),
30
+ }),
31
+ http: { method: "GET" },
32
+ readOnly: true,
33
+ run: async (args): Promise<NotionDatabaseSourcesResponse> => {
34
+ const userEmail = getRequestUserEmail();
35
+ if (!userEmail)
36
+ throw new Error("Notion database access requires a signed-in user.");
37
+ const connection = await getNotionConnectionForOwner(userEmail);
38
+ if (!connection) {
39
+ return {
40
+ connected: false,
41
+ workspaceName: null,
42
+ sources: [],
43
+ hasMore: false,
44
+ nextCursor: null,
45
+ };
46
+ }
47
+ const response = await notionFetch<{
48
+ results?: Array<{
49
+ object?: string;
50
+ id: string;
51
+ url?: string;
52
+ title?: unknown;
53
+ name?: string;
54
+ }>;
55
+ has_more?: boolean;
56
+ next_cursor?: string | null;
57
+ }>("/search", connection.accessToken, {
58
+ method: "POST",
59
+ body: JSON.stringify({
60
+ page_size: args.limit,
61
+ filter: { property: "object", value: "data_source" },
62
+ ...(args.query ? { query: args.query } : {}),
63
+ ...(args.cursor ? { start_cursor: args.cursor } : {}),
64
+ }),
65
+ });
66
+ return {
67
+ connected: true,
68
+ workspaceName: connection.workspaceName,
69
+ sources: (response.results ?? [])
70
+ .filter((result) => result.object === "data_source")
71
+ .map((result) => ({
72
+ id: result.id,
73
+ name: plainText(result.title) || result.name || "Untitled database",
74
+ url: result.url ?? null,
75
+ })),
76
+ hasMore: response.has_more === true,
77
+ nextCursor: response.next_cursor ?? null,
78
+ };
79
+ },
80
+ });
@@ -14,6 +14,7 @@ import {
14
14
  isContentLocalFileMode,
15
15
  moveLocalFileDocument,
16
16
  } from "./_local-file-documents.js";
17
+ import { documentsPositionScope, withPositionLock } from "./_position-utils.js";
17
18
 
18
19
  async function assertParentIsNotDescendant({
19
20
  db,
@@ -282,60 +283,75 @@ export default defineAction({
282
283
  updates.position =
283
284
  normalizedSiblingPositions?.find((document) => document.id === id)
284
285
  ?.position ?? args.position;
285
- } else if (args.parentId !== undefined) {
286
- const parentId = args.parentId;
287
- const maxPos = await db
288
- .select({ max: sql<number>`COALESCE(MAX(position), -1)` })
289
- .from(schema.documents)
290
- .where(
291
- parentId
292
- ? and(
293
- eq(schema.documents.ownerEmail, ownerEmail),
294
- eq(schema.documents.parentId, parentId),
295
- )
296
- : and(
297
- eq(schema.documents.ownerEmail, ownerEmail),
298
- rootSectionFilter(existing),
299
- sql`parent_id IS NULL`,
300
- ),
301
- );
302
- updates.position = (maxPos[0]?.max ?? -1) + 1;
303
286
  }
304
287
 
305
- await db.transaction(async (tx) => {
306
- await tx
307
- .update(schema.documents)
308
- .set(updates)
309
- .where(
310
- and(
311
- eq(schema.documents.id, id),
312
- eq(schema.documents.ownerEmail, ownerEmail),
313
- ),
314
- );
288
+ const runMoveTransaction = () =>
289
+ db.transaction(async (tx) => {
290
+ await tx
291
+ .update(schema.documents)
292
+ .set(updates)
293
+ .where(
294
+ and(
295
+ eq(schema.documents.id, id),
296
+ eq(schema.documents.ownerEmail, ownerEmail),
297
+ ),
298
+ );
315
299
 
316
- if (args.parentId !== undefined && blockDatabaseIdToDetach) {
317
- await clearBlockDatabaseOwnership({
318
- db: tx,
319
- databaseId: blockDatabaseIdToDetach,
320
- ownerEmail,
321
- updatedAt,
322
- });
323
- }
300
+ if (args.parentId !== undefined && blockDatabaseIdToDetach) {
301
+ await clearBlockDatabaseOwnership({
302
+ db: tx,
303
+ databaseId: blockDatabaseIdToDetach,
304
+ ownerEmail,
305
+ updatedAt,
306
+ });
307
+ }
308
+
309
+ if (normalizedSiblingPositions) {
310
+ for (const document of normalizedSiblingPositions) {
311
+ await tx
312
+ .update(schema.documents)
313
+ .set({ position: document.position })
314
+ .where(
315
+ and(
316
+ eq(schema.documents.id, document.id),
317
+ eq(schema.documents.ownerEmail, ownerEmail),
318
+ ),
319
+ );
320
+ }
321
+ }
322
+ });
324
323
 
325
- if (normalizedSiblingPositions) {
326
- for (const document of normalizedSiblingPositions) {
327
- await tx
328
- .update(schema.documents)
329
- .set({ position: document.position })
324
+ if (args.position === undefined && args.parentId !== undefined) {
325
+ // Appending to the end of the new parent's children reads MAX(position)
326
+ // then writes MAX+1. Serialize the read through the write so a
327
+ // concurrent move/create/add targeting the same parent can't read the
328
+ // same MAX and land on the same position (see _position-utils.ts).
329
+ const parentId = args.parentId;
330
+ await withPositionLock(
331
+ documentsPositionScope(ownerEmail, parentId),
332
+ async () => {
333
+ const maxPos = await db
334
+ .select({ max: sql<number>`COALESCE(MAX(position), -1)` })
335
+ .from(schema.documents)
330
336
  .where(
331
- and(
332
- eq(schema.documents.id, document.id),
333
- eq(schema.documents.ownerEmail, ownerEmail),
334
- ),
337
+ parentId
338
+ ? and(
339
+ eq(schema.documents.ownerEmail, ownerEmail),
340
+ eq(schema.documents.parentId, parentId),
341
+ )
342
+ : and(
343
+ eq(schema.documents.ownerEmail, ownerEmail),
344
+ rootSectionFilter(existing),
345
+ sql`parent_id IS NULL`,
346
+ ),
335
347
  );
336
- }
337
- }
338
- });
348
+ updates.position = (maxPos[0]?.max ?? -1) + 1;
349
+ await runMoveTransaction();
350
+ },
351
+ );
352
+ } else {
353
+ await runMoveTransaction();
354
+ }
339
355
 
340
356
  const [doc] = await db
341
357
  .select()
@@ -3,6 +3,7 @@ import { assertAccess } from "@agent-native/core/sharing";
3
3
  import { z } from "zod";
4
4
 
5
5
  import type { ContentDatabaseSourceStatusResponse } from "../shared/api.js";
6
+ import { getContentDatabaseSourceAdapter } from "./_content-database-source-adapters.js";
6
7
  import {
7
8
  getContentDatabaseSourceSnapshot,
8
9
  getContentDatabaseSourceSnapshotById,
@@ -10,12 +11,15 @@ import {
10
11
  resyncBuilderCmsSourceSnapshot,
11
12
  resyncMockSourceSnapshot,
12
13
  resolveDatabaseForSourceMutation,
14
+ seedSecondarySourceFields,
15
+ storeSecondarySourceRows,
16
+ updateReadOnlySourceMetadata,
13
17
  } from "./_database-source-utils.js";
14
18
  import { serializeDatabase } from "./_property-utils.js";
15
19
 
16
20
  export default defineAction({
17
21
  description:
18
- "Refresh the local read-only source status envelope for a content database. Mock-local and Builder CMS fixture sources resync field mappings and row identity without provider writes. For Builder CMS sources, set fullRefresh to true when you need to read every available page in one action call instead of continuing one partial page.",
22
+ "Refresh the local read-only source status envelope for a content database. Mock-local, Builder CMS, and Notion database sources resync field mappings and row identity without provider writes. For paginated Builder CMS or Notion sources, set fullRefresh to true to read a bounded multi-page snapshot in one action call.",
19
23
  schema: z.object({
20
24
  databaseId: z.string().optional().describe("Database ID"),
21
25
  documentId: z.string().optional().describe("Database document/page ID"),
@@ -27,7 +31,7 @@ export default defineAction({
27
31
  .boolean()
28
32
  .optional()
29
33
  .describe(
30
- "For Builder CMS sources, read all available pages in this refresh instead of one continuation page.",
34
+ "For paginated Builder CMS or Notion sources, read a bounded multi-page snapshot in this refresh.",
31
35
  ),
32
36
  }),
33
37
  run: async (args): Promise<ContentDatabaseSourceStatusResponse> => {
@@ -58,6 +62,39 @@ export default defineAction({
58
62
  } else if (source.sourceType === "local-table") {
59
63
  // Read-only federated secondary; its rows are re-read on demand, nothing
60
64
  // to resync against the primary's local snapshot here.
65
+ } else if (source.sourceType === "notion-database") {
66
+ const adapter = getContentDatabaseSourceAdapter("notion-database");
67
+ const read = await adapter!.read({
68
+ sourceTable: source.sourceTable,
69
+ limit: 500,
70
+ offset: 0,
71
+ fullRefresh: args.fullRefresh === true,
72
+ });
73
+ await storeSecondarySourceRows({
74
+ sourceId: source.id,
75
+ ownerEmail: database.ownerEmail,
76
+ sourceType: "notion-database",
77
+ sourceTable: source.sourceTable,
78
+ entries: read.entries,
79
+ now,
80
+ });
81
+ await seedSecondarySourceFields({
82
+ sourceId: source.id,
83
+ ownerEmail: database.ownerEmail,
84
+ sourceType: "notion-database",
85
+ modelFields: read.fields,
86
+ sampleEntry: read.entries[0],
87
+ now,
88
+ });
89
+ await updateReadOnlySourceMetadata({
90
+ sourceId: source.id,
91
+ sourceType: "notion-database",
92
+ sourceTable: source.sourceTable,
93
+ fetchedAt: read.fetchedAt,
94
+ now,
95
+ message: read.message,
96
+ metadata: read.metadata,
97
+ });
61
98
  } else {
62
99
  throw new Error(`Unsupported source type "${source.sourceType}".`);
63
100
  }
@@ -81,7 +118,9 @@ export default defineAction({
81
118
  summary: snapshot
82
119
  ? builderFetching
83
120
  ? `${snapshot.sourceName} fetched ${builderFetched ?? "some"} rows. Run refresh again to continue loading the remaining Builder rows.`
84
- : `${snapshot.sourceName} resynced locally; field mappings and row identity now reflect the current database snapshot.`
121
+ : snapshot.sourceType === "notion-database"
122
+ ? `${snapshot.sourceName} refreshed read-only from Notion.`
123
+ : `${snapshot.sourceName} resynced locally; field mappings and row identity now reflect the current database snapshot.`
85
124
  : "Source metadata refreshed.",
86
125
  source: snapshot,
87
126
  };
@@ -19,6 +19,7 @@ import {
19
19
  isLocalFileDocumentId,
20
20
  localDocumentPathFromId,
21
21
  } from "./_local-file-documents.js";
22
+ import { documentsPositionScope, withPositionLock } from "./_position-utils.js";
22
23
 
23
24
  function nanoid(size = 12): string {
24
25
  const chars =
@@ -123,34 +124,42 @@ export default defineAction({
123
124
  return serializeDocument(row);
124
125
  }
125
126
 
126
- const [{ max: maxPosition } = { max: -1 }] = await db
127
- .select({ max: sql<number>`COALESCE(MAX(position), -1)` })
128
- .from(schema.documents)
129
- .where(
130
- and(eq(schema.documents.ownerEmail, userEmail), sql`parent_id IS NULL`),
131
- );
132
-
133
127
  const documentId = nanoid();
134
- await db.insert(schema.documents).values({
135
- id: documentId,
136
- ownerEmail: userEmail,
137
- orgId,
138
- parentId: null,
139
- title: localDocument.title,
140
- content: localDocument.content,
141
- icon: localDocument.icon,
142
- position: (maxPosition ?? -1) + 1,
143
- isFavorite: localDocument.isFavorite ? 1 : 0,
144
- hideFromSearch: localDocument.hideFromSearch ? 1 : 0,
145
- visibility: "private",
146
- sourceMode: "database",
147
- sourceKind: "local-file-copy",
148
- sourcePath,
149
- sourceRootPath: localDocument.source?.rootPath ?? null,
150
- sourceUpdatedAt: localDocument.source?.updatedAt ?? now,
151
- createdAt: now,
152
- updatedAt: now,
153
- });
128
+ await withPositionLock(
129
+ documentsPositionScope(userEmail, null),
130
+ async () => {
131
+ const [{ max: maxPosition } = { max: -1 }] = await db
132
+ .select({ max: sql<number>`COALESCE(MAX(position), -1)` })
133
+ .from(schema.documents)
134
+ .where(
135
+ and(
136
+ eq(schema.documents.ownerEmail, userEmail),
137
+ sql`parent_id IS NULL`,
138
+ ),
139
+ );
140
+
141
+ await db.insert(schema.documents).values({
142
+ id: documentId,
143
+ ownerEmail: userEmail,
144
+ orgId,
145
+ parentId: null,
146
+ title: localDocument.title,
147
+ content: localDocument.content,
148
+ icon: localDocument.icon,
149
+ position: (maxPosition ?? -1) + 1,
150
+ isFavorite: localDocument.isFavorite ? 1 : 0,
151
+ hideFromSearch: localDocument.hideFromSearch ? 1 : 0,
152
+ visibility: "private",
153
+ sourceMode: "database",
154
+ sourceKind: "local-file-copy",
155
+ sourcePath,
156
+ sourceRootPath: localDocument.source?.rootPath ?? null,
157
+ sourceUpdatedAt: localDocument.source?.updatedAt ?? now,
158
+ createdAt: now,
159
+ updatedAt: now,
160
+ });
161
+ },
162
+ );
154
163
 
155
164
  const [row] = await db
156
165
  .select()
@@ -10,10 +10,12 @@ import {
10
10
  readBuilderCmsContentEntries,
11
11
  readBuilderCmsModelFields,
12
12
  } from "./_builder-cms-read-client.js";
13
+ import { getContentDatabaseSourceAdapter } from "./_content-database-source-adapters.js";
13
14
  import {
14
15
  getContentDatabaseSourceSnapshot,
15
16
  resolveDatabaseForSourceMutation,
16
17
  } from "./_database-source-utils.js";
18
+ import { getContentDatabaseResponse } from "./_database-utils.js";
17
19
  import { suggestJoinKey } from "./_join-suggestion.js";
18
20
  import { readLocalTableEntries } from "./_local-table-source.js";
19
21
 
@@ -23,7 +25,12 @@ export default defineAction({
23
25
  schema: z.object({
24
26
  databaseId: z.string().optional().describe("Database ID"),
25
27
  documentId: z.string().optional().describe("Database document/page ID"),
26
- candidateSourceType: z.enum(["mock-local", "builder-cms", "local-table"]),
28
+ candidateSourceType: z.enum([
29
+ "mock-local",
30
+ "builder-cms",
31
+ "local-table",
32
+ "notion-database",
33
+ ]),
27
34
  candidateSourceTable: z
28
35
  .string()
29
36
  .describe("Model/table name of the source being added."),
@@ -38,23 +45,39 @@ export default defineAction({
38
45
  if (!access) throw new Error(`Database "${database.id}" not found`);
39
46
 
40
47
  const primary = await getContentDatabaseSourceSnapshot(database);
41
- if (!primary) {
42
- return {
43
- state: "no-primary",
44
- suggestion: null,
45
- message: "Attach a first source before federating a second one.",
46
- };
47
- }
48
-
49
- const primaryValues = primary.rows
50
- .map((row) => row.sourceValues)
51
- .filter((values): values is Record<string, DocumentPropertyValue> =>
52
- Boolean(values),
53
- )
54
- .slice(0, args.sampleLimit);
48
+ const primaryValues = primary
49
+ ? primary.rows
50
+ .map((row) => row.sourceValues)
51
+ .filter((values): values is Record<string, DocumentPropertyValue> =>
52
+ Boolean(values),
53
+ )
54
+ .slice(0, args.sampleLimit)
55
+ : (
56
+ await getContentDatabaseResponse(database.id, {
57
+ limit: args.sampleLimit,
58
+ offset: 0,
59
+ })
60
+ ).items.map((item) => ({
61
+ title: item.document.title ?? "",
62
+ ...Object.fromEntries(
63
+ item.properties
64
+ .filter((property) => !!property.definition.id)
65
+ .map((property) => [property.definition.id, property.value]),
66
+ ),
67
+ }));
55
68
 
56
69
  let secondaryValues: Record<string, DocumentPropertyValue>[];
57
- if (args.candidateSourceType === "builder-cms") {
70
+ if (args.candidateSourceType === "notion-database") {
71
+ const adapter = getContentDatabaseSourceAdapter(args.candidateSourceType);
72
+ const read = await adapter!.read({
73
+ sourceTable: args.candidateSourceTable,
74
+ limit: args.sampleLimit,
75
+ offset: 0,
76
+ });
77
+ secondaryValues = read.entries
78
+ .map((entry) => entry.sourceValues)
79
+ .slice(0, args.sampleLimit);
80
+ } else if (args.candidateSourceType === "builder-cms") {
58
81
  const modelFields = await readBuilderCmsModelFields({
59
82
  model: args.candidateSourceTable,
60
83
  }).catch(() => []);