@agent-native/core 0.102.2 → 0.103.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 (206) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +6 -0
  3. package/corpus/core/docs/content/local-file-mode.mdx +99 -489
  4. package/corpus/core/docs/content/locales/ar-SA/local-file-mode.mdx +35 -490
  5. package/corpus/core/docs/content/locales/ar-SA/template-content.mdx +10 -24
  6. package/corpus/core/docs/content/locales/de-DE/local-file-mode.mdx +37 -491
  7. package/corpus/core/docs/content/locales/de-DE/template-content.mdx +10 -24
  8. package/corpus/core/docs/content/locales/es-ES/local-file-mode.mdx +35 -493
  9. package/corpus/core/docs/content/locales/es-ES/template-content.mdx +10 -24
  10. package/corpus/core/docs/content/locales/fr-FR/local-file-mode.mdx +38 -491
  11. package/corpus/core/docs/content/locales/fr-FR/template-content.mdx +10 -24
  12. package/corpus/core/docs/content/locales/hi-IN/local-file-mode.mdx +33 -492
  13. package/corpus/core/docs/content/locales/hi-IN/template-content.mdx +10 -24
  14. package/corpus/core/docs/content/locales/ja-JP/local-file-mode.mdx +36 -492
  15. package/corpus/core/docs/content/locales/ja-JP/template-content.mdx +10 -24
  16. package/corpus/core/docs/content/locales/ko-KR/local-file-mode.mdx +35 -490
  17. package/corpus/core/docs/content/locales/ko-KR/template-content.mdx +10 -24
  18. package/corpus/core/docs/content/locales/pt-BR/local-file-mode.mdx +35 -493
  19. package/corpus/core/docs/content/locales/pt-BR/template-content.mdx +10 -24
  20. package/corpus/core/docs/content/locales/zh-CN/local-file-mode.mdx +31 -489
  21. package/corpus/core/docs/content/locales/zh-CN/template-content.mdx +9 -24
  22. package/corpus/core/docs/content/locales/zh-TW/local-file-mode.mdx +31 -489
  23. package/corpus/core/docs/content/locales/zh-TW/template-content.mdx +9 -24
  24. package/corpus/core/docs/content/template-content.mdx +26 -42
  25. package/corpus/core/package.json +1 -1
  26. package/corpus/core/src/cli/content-local.ts +86 -18
  27. package/corpus/core/src/cli/index.ts +2 -2
  28. package/corpus/core/src/cli/skills-content/content-skill.ts +36 -25
  29. package/corpus/core/src/cli/skills.ts +47 -13
  30. package/corpus/core/src/local-artifacts/index.ts +65 -0
  31. package/corpus/templates/assets/app/components/library/GenerationPresetsPanel.tsx +325 -0
  32. package/corpus/templates/assets/app/hooks/use-navigation-state.ts +12 -0
  33. package/corpus/templates/assets/app/i18n/zh-TW.ts +21 -0
  34. package/corpus/templates/assets/app/i18n-data.ts +215 -0
  35. package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +19 -479
  36. package/corpus/templates/assets/app/routes/brand-kits.$id_.presets.$presetId.tsx +1 -1
  37. package/corpus/templates/assets/app/routes/brand-kits.$id_.settings.tsx +446 -0
  38. package/corpus/templates/clips/app/components/editor/editor-layout.tsx +12 -2
  39. package/corpus/templates/clips/app/components/player/settings-panel.tsx +30 -12
  40. package/corpus/templates/clips/app/components/player/video-player.tsx +5 -1
  41. package/corpus/templates/clips/app/components/recorder/microphone-visualizer.tsx +22 -3
  42. package/corpus/templates/clips/app/i18n/ar-SA.ts +3 -2
  43. package/corpus/templates/clips/app/i18n/de-DE.ts +4 -2
  44. package/corpus/templates/clips/app/i18n/en-US.ts +3 -2
  45. package/corpus/templates/clips/app/i18n/es-ES.ts +4 -2
  46. package/corpus/templates/clips/app/i18n/fr-FR.ts +3 -2
  47. package/corpus/templates/clips/app/i18n/hi-IN.ts +3 -2
  48. package/corpus/templates/clips/app/i18n/ja-JP.ts +4 -1
  49. package/corpus/templates/clips/app/i18n/ko-KR.ts +3 -2
  50. package/corpus/templates/clips/app/i18n/pt-BR.ts +4 -2
  51. package/corpus/templates/clips/app/i18n/zh-CN.ts +3 -2
  52. package/corpus/templates/clips/app/i18n/zh-TW.ts +3 -2
  53. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +27 -1
  54. package/corpus/templates/clips/server/lib/share-password.ts +6 -3
  55. package/corpus/templates/content/.agents/skills/content/SKILL.md +26 -39
  56. package/corpus/templates/content/AGENTS.md +25 -30
  57. package/corpus/templates/content/actions/_builder-docs-client.ts +23 -0
  58. package/corpus/templates/content/actions/_content-database-source-adapters.ts +21 -3
  59. package/corpus/templates/content/actions/_content-files.ts +338 -0
  60. package/corpus/templates/content/actions/_content-space-access.ts +135 -0
  61. package/corpus/templates/content/actions/_content-spaces.ts +640 -0
  62. package/corpus/templates/content/actions/_database-source-utils.ts +90 -7
  63. package/corpus/templates/content/actions/_database-utils.ts +7 -1
  64. package/corpus/templates/content/actions/_local-file-documents.ts +0 -9
  65. package/corpus/templates/content/actions/_local-folder-source.ts +53 -0
  66. package/corpus/templates/content/actions/_property-utils.ts +9 -4
  67. package/corpus/templates/content/actions/add-database-item.ts +108 -65
  68. package/corpus/templates/content/actions/backfill-content-files.ts +22 -0
  69. package/corpus/templates/content/actions/connect-local-folder-source.ts +221 -0
  70. package/corpus/templates/content/actions/create-content-database.ts +129 -3
  71. package/corpus/templates/content/actions/create-document.ts +65 -55
  72. package/corpus/templates/content/actions/create-inline-content-database.ts +6 -1
  73. package/corpus/templates/content/actions/delete-content-database.ts +3 -0
  74. package/corpus/templates/content/actions/delete-document.ts +7 -11
  75. package/corpus/templates/content/actions/disconnect-local-folder-source.ts +175 -0
  76. package/corpus/templates/content/actions/duplicate-database-item.ts +10 -0
  77. package/corpus/templates/content/actions/duplicate-database-items.ts +13 -0
  78. package/corpus/templates/content/actions/edit-document.ts +2 -28
  79. package/corpus/templates/content/actions/ensure-content-spaces.ts +26 -0
  80. package/corpus/templates/content/actions/export-content-source.ts +47 -9
  81. package/corpus/templates/content/actions/get-document.ts +0 -14
  82. package/corpus/templates/content/actions/import-content-source.ts +43 -3
  83. package/corpus/templates/content/actions/list-content-spaces.ts +103 -0
  84. package/corpus/templates/content/actions/list-documents.ts +12 -9
  85. package/corpus/templates/content/actions/move-document.ts +3 -14
  86. package/corpus/templates/content/actions/pull-document.ts +0 -23
  87. package/corpus/templates/content/actions/remove-local-file-source.ts +50 -29
  88. package/corpus/templates/content/actions/resolve-local-folder-conflict.ts +442 -0
  89. package/corpus/templates/content/actions/reveal-local-source-file.ts +6 -17
  90. package/corpus/templates/content/actions/search-documents.ts +0 -34
  91. package/corpus/templates/content/actions/share-local-file-document.ts +25 -1
  92. package/corpus/templates/content/actions/submit-content-database-form.ts +12 -0
  93. package/corpus/templates/content/actions/sync-local-folder-source.ts +731 -0
  94. package/corpus/templates/content/actions/sync-manifest-local-folder-source.ts +123 -0
  95. package/corpus/templates/content/actions/update-content-database-view.ts +10 -1
  96. package/corpus/templates/content/actions/update-document.ts +0 -15
  97. package/corpus/templates/content/actions/view-screen.ts +2 -50
  98. package/corpus/templates/content/app/components/editor/SlashCommandMenu.tsx +76 -62
  99. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +70 -22
  100. package/corpus/templates/content/app/components/editor/database/grouping.ts +2 -1
  101. package/corpus/templates/content/app/components/editor/database/settings.tsx +23 -20
  102. package/corpus/templates/content/app/components/editor/database/shared.tsx +2 -0
  103. package/corpus/templates/content/app/components/editor/database/sidebar.tsx +330 -0
  104. package/corpus/templates/content/app/components/editor/database/types.ts +1 -0
  105. package/corpus/templates/content/app/components/editor/database/view-config.ts +3 -1
  106. package/corpus/templates/content/app/components/layout/Layout.tsx +25 -1
  107. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +209 -113
  108. package/corpus/templates/content/app/components/sidebar/select-content-space.ts +31 -0
  109. package/corpus/templates/content/app/hooks/use-content-database.ts +16 -0
  110. package/corpus/templates/content/app/hooks/use-content-spaces.ts +39 -0
  111. package/corpus/templates/content/app/i18n/zh-TW.ts +11 -0
  112. package/corpus/templates/content/app/i18n-data.ts +75 -0
  113. package/corpus/templates/content/app/routes/_app.local-files.tsx +174 -65
  114. package/corpus/templates/content/changelog/2026-07-16-content-callouts-can-now-be-reviewed-and-published-to-builder.md +6 -0
  115. package/corpus/templates/content/changelog/2026-07-16-heading-5-and-heading-6-are-available-from-the-editor-slash-.md +6 -0
  116. package/corpus/templates/content/changelog/2026-07-16-organize-every-workspace-through-a-customizable-files-databa.md +6 -0
  117. package/corpus/templates/content/parity/matrix.md +2 -1
  118. package/corpus/templates/content/parity/matrix.ts +37 -1
  119. package/corpus/templates/content/scripts/dev-database.mjs +7 -5
  120. package/corpus/templates/content/server/db/schema.ts +113 -40
  121. package/corpus/templates/content/server/lib/document-context.ts +15 -1
  122. package/corpus/templates/content/server/lib/notion-sync.ts +6 -0
  123. package/corpus/templates/content/server/plugins/db.ts +153 -0
  124. package/corpus/templates/content/shared/api.ts +17 -3
  125. package/corpus/templates/content/shared/builder-mdx.ts +163 -16
  126. package/corpus/templates/design/.agents/skills/design-templates/SKILL.md +59 -0
  127. package/corpus/templates/design/AGENTS.md +6 -1
  128. package/corpus/templates/design/actions/create-design-from-template.ts +19 -7
  129. package/corpus/templates/design/actions/list-design-templates.ts +69 -21
  130. package/corpus/templates/design/actions/navigate.ts +2 -2
  131. package/corpus/templates/design/actions/view-screen.ts +15 -2
  132. package/corpus/templates/design/agent-native.app-skill.json +5 -0
  133. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +281 -56
  134. package/corpus/templates/design/app/components/templates/TemplatePreview.tsx +14 -2
  135. package/corpus/templates/design/app/hooks/use-navigation-state.ts +3 -2
  136. package/corpus/templates/design/app/i18n/zh-TW.ts +3 -3
  137. package/corpus/templates/design/app/i18n-data.ts +21 -2
  138. package/corpus/templates/design/app/i18n-template-feature.ts +218 -10
  139. package/corpus/templates/design/app/pages/Index.tsx +195 -24
  140. package/corpus/templates/design/app/pages/Templates.tsx +144 -55
  141. package/corpus/templates/design/app/pages/design-editor/generation-prompt-directives.ts +12 -1
  142. package/corpus/templates/design/changelog/2026-07-14-templates-now-appear-in-the-new-design-picker-with-previews-.md +6 -0
  143. package/corpus/templates/design/changelog/2026-07-15-templates-now-open-immediately-after-copying-even-while-the-.md +6 -0
  144. package/corpus/templates/design/server/plugins/agent-chat.ts +1 -1
  145. package/corpus/templates/mail/AGENTS.md +23 -18
  146. package/corpus/templates/mail/actions/bulk-archive.ts +32 -28
  147. package/corpus/templates/mail/actions/mark-read.ts +131 -20
  148. package/corpus/templates/mail/actions/mark-thread-read.ts +1 -1
  149. package/corpus/templates/mail/actions/move-email.ts +30 -24
  150. package/corpus/templates/mail/actions/send-email.ts +73 -68
  151. package/corpus/templates/mail/changelog/2026-07-15-unread-inbox-cleanup-now-completes-reliably.md +6 -0
  152. package/corpus/templates/mail/server/handlers/emails.ts +218 -209
  153. package/corpus/templates/mail/server/lib/bulk-mark-read.ts +30 -0
  154. package/corpus/templates/mail/server/lib/email-state.ts +198 -113
  155. package/corpus/templates/mail/server/lib/google-auth.ts +218 -25
  156. package/corpus/templates/mail/server/lib/jobs.ts +69 -74
  157. package/corpus/templates/mail/server/lib/local-email-store.ts +265 -0
  158. package/corpus/templates/mail/server/plugins/agent-chat.ts +6 -0
  159. package/dist/cli/content-local.d.ts +1 -0
  160. package/dist/cli/content-local.d.ts.map +1 -1
  161. package/dist/cli/content-local.js +75 -17
  162. package/dist/cli/content-local.js.map +1 -1
  163. package/dist/cli/index.js +2 -2
  164. package/dist/cli/index.js.map +1 -1
  165. package/dist/cli/skills-content/content-skill.d.ts +1 -1
  166. package/dist/cli/skills-content/content-skill.d.ts.map +1 -1
  167. package/dist/cli/skills-content/content-skill.js +36 -25
  168. package/dist/cli/skills-content/content-skill.js.map +1 -1
  169. package/dist/cli/skills.d.ts.map +1 -1
  170. package/dist/cli/skills.js +47 -14
  171. package/dist/cli/skills.js.map +1 -1
  172. package/dist/collab/awareness.d.ts +2 -2
  173. package/dist/collab/awareness.d.ts.map +1 -1
  174. package/dist/collab/struct-routes.d.ts +1 -1
  175. package/dist/local-artifacts/index.d.ts +10 -0
  176. package/dist/local-artifacts/index.d.ts.map +1 -1
  177. package/dist/local-artifacts/index.js +39 -0
  178. package/dist/local-artifacts/index.js.map +1 -1
  179. package/dist/notifications/routes.d.ts +1 -1
  180. package/dist/observability/routes.d.ts +5 -5
  181. package/dist/resources/handlers.d.ts +1 -1
  182. package/dist/secrets/routes.d.ts +9 -9
  183. package/docs/content/local-file-mode.mdx +99 -489
  184. package/docs/content/locales/ar-SA/local-file-mode.mdx +35 -490
  185. package/docs/content/locales/ar-SA/template-content.mdx +10 -24
  186. package/docs/content/locales/de-DE/local-file-mode.mdx +37 -491
  187. package/docs/content/locales/de-DE/template-content.mdx +10 -24
  188. package/docs/content/locales/es-ES/local-file-mode.mdx +35 -493
  189. package/docs/content/locales/es-ES/template-content.mdx +10 -24
  190. package/docs/content/locales/fr-FR/local-file-mode.mdx +38 -491
  191. package/docs/content/locales/fr-FR/template-content.mdx +10 -24
  192. package/docs/content/locales/hi-IN/local-file-mode.mdx +33 -492
  193. package/docs/content/locales/hi-IN/template-content.mdx +10 -24
  194. package/docs/content/locales/ja-JP/local-file-mode.mdx +36 -492
  195. package/docs/content/locales/ja-JP/template-content.mdx +10 -24
  196. package/docs/content/locales/ko-KR/local-file-mode.mdx +35 -490
  197. package/docs/content/locales/ko-KR/template-content.mdx +10 -24
  198. package/docs/content/locales/pt-BR/local-file-mode.mdx +35 -493
  199. package/docs/content/locales/pt-BR/template-content.mdx +10 -24
  200. package/docs/content/locales/zh-CN/local-file-mode.mdx +31 -489
  201. package/docs/content/locales/zh-CN/template-content.mdx +9 -24
  202. package/docs/content/locales/zh-TW/local-file-mode.mdx +31 -489
  203. package/docs/content/locales/zh-TW/template-content.mdx +9 -24
  204. package/docs/content/template-content.mdx +26 -42
  205. package/package.json +1 -1
  206. package/corpus/templates/assets/app/components/library/EditLibraryDialog.tsx +0 -126
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: added
3
+ date: 2026-07-16
4
+ ---
5
+
6
+ Organize every workspace through a customizable Files database and sync local folders into the same database-backed experience.
@@ -15,7 +15,7 @@ This generated matrix tracks whether high-value Content UI operations use the sa
15
15
  | editor.document-body-and-title | editor | Edit document title, body, icon, image alt text, and precise text | action-backed | `edit-document`, `pull-document`, `set-image-alt-text`, `transcribe-media`, `update-document` | `app/components/editor/DocumentEditor.tsx`, `app/components/editor/DocumentDatabase.tsx`, `app/components/editor/extensions/ImageBlock.tsx`, `app/components/editor/SlashCommandMenu.tsx` | Document content, title, icon, image metadata, and text replacements are saved to the same document source. | - | - | P0 | covered | `actions/content-database-lifecycle.db.test.ts`, `actions/_local-file-documents.test.ts` | `document-search-edit` | - |
16
16
  | local-files.components-workspace | local-files | Register, list, and write local MDX component workspaces | host-only | `list-local-component-files`, `register-local-component-workspace`, `write-local-component-file` | `app/routes/_app.local-files.tsx`, `actions/register-local-component-workspace.ts`, `actions/list-local-component-files.ts`, `actions/write-local-component-file.ts` | Trusted local component workspace registration and component file reads/writes support local MDX previews. | Workspace registration depends on a trusted Desktop folder path and is intentionally hidden with agentTool: false. | - | P1 | seeded | - | - | Local folder exception/docs PR |
17
17
  | local-files.host-folder-handles | local-files | Choose, persist, remove, and write trusted local folder handles | host-only | - | `app/routes/_app.local-files.tsx` | Host directory handles and browser/Desktop write permissions are managed outside SQL action state. | Mounted local folders require browser/Desktop host handles that agents cannot safely or portably hold as normal tools. | - | P0 | none | - | - | Local folder exception/docs PR |
18
- | local-files.import-export-mounted-folder | local-files | Import, check, export, push, and remove local folder source files | action-backed | `export-content-source`, `import-content-source`, `remove-local-file-source` | `app/routes/_app.local-files.tsx`, `actions/import-content-source.ts`, `actions/export-content-source.ts` | Local Markdown/MDX source files are imported into Content documents, editable Content documents are exported back to source-friendly files, and imported source entries can be removed without deleting files on disk. | - | - | P0 | covered | `actions/_local-file-documents.test.ts` | `local-file-source-truth` | - |
18
+ | local-files.import-export-mounted-folder | local-files | Import, check, export, push, and remove local folder source files | action-backed | `connect-local-folder-source`, `disconnect-local-folder-source`, `export-content-source`, `import-content-source`, `remove-local-file-source`, `resolve-local-folder-conflict`, `sync-local-folder-source`, `sync-manifest-local-folder-source` | `app/routes/_app.local-files.tsx`, `actions/import-content-source.ts`, `actions/export-content-source.ts` | Local Markdown/MDX source files are imported into Content documents, editable Content documents are exported back to source-friendly files, and imported source entries can be removed without deleting files on disk. | - | - | P0 | covered | `actions/_local-file-documents.test.ts`, `actions/local-folder-source.db.test.ts` | `local-file-source-truth` | - |
19
19
  | notion.route-backed-document-sync | source-sync | Notion document sync status, link, unlink, pull, push, resolve, create, search, and disconnect | action-backed | `connect-notion-status`, `create-and-link-notion-page`, `disconnect-notion`, `link-notion-page`, `list-notion-links`, `pull-notion-page`, `push-notion-page`, `refresh-notion-sync-status`, `resolve-notion-sync-conflict`, `search-notion-pages`, `sync-notion-comments`, `unlink-notion-page` | `app/hooks/use-notion.ts`, `app/components/editor/DocumentToolbar.tsx`, `app/components/editor/NotionSyncBar.tsx`, `app/components/editor/DocumentEditor.tsx` | Notion connection state, page search, link metadata, and local/remote document body sync state are read or mutated through Content actions. | Notion OAuth auth-url and callback routes remain route-shaped because they initiate and receive browser redirects rather than normal app data mutations. | - | P0 | covered | `parity/__tests__/matrix-route-gap-classify.test.ts` | - | - |
20
20
  | sharing.document-discoverability-and-export | sharing | Share, hide from search, export, and reveal documents | action-backed | `export-document`, `reveal-local-source-file`, `set-document-discoverability`, `share-local-file-document` | `app/components/editor/DocumentToolbar.tsx`, `app/hooks/use-documents.ts` | Search discoverability, shareable copies, exports, and OS reveal requests are managed through Content actions. | - | - | P0 | covered | `actions/_local-file-documents.test.ts` | `local-file-source-truth` | - |
21
21
  | sharing.os-reveal-local-source | sharing | Reveal a local source file in the system file manager | host-only | `reveal-local-source-file` | `app/components/editor/DocumentToolbar.tsx`, `actions/reveal-local-source-file.ts` | - | OS reveal depends on trusted local host capabilities and should not spend agent tool surface or imply portable hosted behavior. | - | P2 | seeded | - | - | Local folder exception/docs PR |
@@ -29,3 +29,4 @@ This generated matrix tracks whether high-value Content UI operations use the sa
29
29
  | source-sync.database-source-bindings | source-sync | Attach, inspect, refresh, disconnect, join, and bind database sources | action-backed | `add-content-database-source-field-property`, `attach-content-database-source`, `bind-content-database-source-field`, `change-content-database-source-role`, `disconnect-content-database-source`, `get-content-database-source`, `list-builder-cms-models`, `list-notion-database-sources`, `refresh-content-database-source`, `suggest-source-join-key` | `app/components/editor/DocumentDatabase.tsx`, `app/components/editor/DocumentProperties.tsx`, `app/components/editor/database/DatabaseView.tsx`, `app/hooks/use-content-database.ts` | Mounted database source metadata, fields, source role, join keys, and source-field/property bindings are stored and refreshed. | - | - | P0 | covered | `actions/bind-content-database-source-field.db.test.ts`, `actions/content-database-source-actions.test.ts`, `actions/resync-content-database-source.db.test.ts` | `database-source-scope` | - |
30
30
  | source-sync.provider-api-and-staged-datasets | source-sync | Inspect provider APIs and stage/query/delete large provider datasets | action-backed | `delete-staged-dataset`, `list-staged-datasets`, `provider-api-catalog`, `provider-api-docs`, `provider-api-request`, `query-staged-dataset` | `actions/provider-api-catalog.ts`, `actions/provider-api-docs.ts`, `actions/provider-api-request.ts`, `actions/query-staged-dataset.ts` | Provider API metadata and staged dataset scratch storage support scoped agent/source analysis. | - | - | P1 | seeded | - | - | - |
31
31
  | versions.history-and-restore | versions | Open version history and restore a previous document version | action-backed | `list-document-versions`, `restore-document-version` | `app/components/editor/VersionHistoryPanel.tsx`, `app/hooks/use-document-versions.ts` | Document versions are listed and selected versions can restore the document while snapshotting current state. | - | - | P0 | seeded | - | - | - |
32
+ | workspace.spaces-and-files-catalog | workspace | Provision and navigate Content spaces through Files and Workspaces | action-backed | `backfill-content-files`, `ensure-content-spaces`, `list-content-spaces` | `app/components/sidebar/DocumentSidebar.tsx`, `app/hooks/use-content-spaces.ts` | Personal and organization spaces, their canonical Files databases, and the personal Workspaces catalog are provisioned and reconciled in SQL. | - | - | P0 | covered | `actions/content-spaces.db.test.ts`, `actions/content-files.db.test.ts` | - | - |
@@ -35,6 +35,34 @@ export const parityMatrix: ParityRow[] = [
35
35
  ],
36
36
  evalScenarioIds: ["document-search-edit"],
37
37
  },
38
+ {
39
+ id: "workspace.spaces-and-files-catalog",
40
+ surface: "workspace",
41
+ label: "Provision and navigate Content spaces through Files and Workspaces",
42
+ uiEntrypoints: [
43
+ "app/components/sidebar/DocumentSidebar.tsx",
44
+ "app/hooks/use-content-spaces.ts",
45
+ ],
46
+ durableEffect:
47
+ "Personal and organization spaces, their canonical Files databases, and the personal Workspaces catalog are provisioned and reconciled in SQL.",
48
+ uiImplementation:
49
+ "The app sidebar calls the shared space actions and renders the selected Files database through a saved sidebar view.",
50
+ status: "action-backed",
51
+ actions: [
52
+ "backfill-content-files",
53
+ "ensure-content-spaces",
54
+ "list-content-spaces",
55
+ ],
56
+ exception: null,
57
+ reliabilityRisk: "none",
58
+ spinePriority: "P0",
59
+ testCoverage: "covered",
60
+ followUpPR: null,
61
+ coverageRefs: [
62
+ "actions/content-spaces.db.test.ts",
63
+ "actions/content-files.db.test.ts",
64
+ ],
65
+ },
38
66
  {
39
67
  id: "sidebar.navigation-and-screen-context",
40
68
  surface: "sidebar",
@@ -537,16 +565,24 @@ export const parityMatrix: ParityRow[] = [
537
565
  "UI reads/writes browser or Desktop folder handles around import/export actions.",
538
566
  status: "action-backed",
539
567
  actions: [
568
+ "connect-local-folder-source",
569
+ "disconnect-local-folder-source",
540
570
  "export-content-source",
541
571
  "import-content-source",
542
572
  "remove-local-file-source",
573
+ "resolve-local-folder-conflict",
574
+ "sync-local-folder-source",
575
+ "sync-manifest-local-folder-source",
543
576
  ],
544
577
  exception: null,
545
578
  reliabilityRisk: "none",
546
579
  spinePriority: "P0",
547
580
  testCoverage: "covered",
548
581
  followUpPR: null,
549
- coverageRefs: ["actions/_local-file-documents.test.ts"],
582
+ coverageRefs: [
583
+ "actions/_local-file-documents.test.ts",
584
+ "actions/local-folder-source.db.test.ts",
585
+ ],
550
586
  evalScenarioIds: ["local-file-source-truth"],
551
587
  },
552
588
  {
@@ -37,8 +37,8 @@ function ensureLocalEnv() {
37
37
  const values = parseEnv(existing);
38
38
  let changed = false;
39
39
 
40
- if (values.get("AGENT_NATIVE_MODE") !== "database") {
41
- values.set("AGENT_NATIVE_MODE", "database");
40
+ if (values.get("AGENT_NATIVE_MODE") === "database") {
41
+ values.delete("AGENT_NATIVE_MODE");
42
42
  changed = true;
43
43
  }
44
44
  const authSecret = values.get("BETTER_AUTH_SECRET") ?? "";
@@ -49,15 +49,17 @@ function ensureLocalEnv() {
49
49
 
50
50
  if (changed) {
51
51
  writeFileSync(envPath, serializeEnv(values));
52
- console.log("[content dev] Wrote local database-mode env to .env.local");
52
+ console.log("[content dev] Updated local Content env in .env.local");
53
53
  }
54
54
  return values;
55
55
  }
56
56
 
57
57
  const envValues = ensureLocalEnv();
58
+ const baseEnv = { ...process.env };
59
+ delete baseEnv.AGENT_NATIVE_MODE;
60
+ delete baseEnv.AGENT_NATIVE_DATA_MODE;
58
61
  const childEnv = {
59
- ...process.env,
60
- AGENT_NATIVE_MODE: "database",
62
+ ...baseEnv,
61
63
  BETTER_AUTH_SECRET:
62
64
  process.env.BETTER_AUTH_SECRET || envValues.get("BETTER_AUTH_SECRET"),
63
65
  };
@@ -11,6 +11,7 @@ import {
11
11
 
12
12
  export const documents = table("documents", {
13
13
  id: text("id").primaryKey(),
14
+ spaceId: text("space_id"),
14
15
  parentId: text("parent_id"),
15
16
  title: text("title").notNull().default("Untitled"),
16
17
  content: text("content").notNull().default(""),
@@ -31,6 +32,58 @@ export const documents = table("documents", {
31
32
  ...ownableColumns(),
32
33
  });
33
34
 
35
+ export const contentSpaces = table(
36
+ "content_spaces",
37
+ {
38
+ id: text("id").primaryKey(),
39
+ name: text("name").notNull(),
40
+ kind: text("kind").notNull(),
41
+ ownerEmail: text("owner_email").notNull(),
42
+ orgId: text("org_id"),
43
+ filesDatabaseId: text("files_database_id").notNull(),
44
+ createdBy: text("created_by").notNull(),
45
+ archivedAt: text("archived_at"),
46
+ createdAt: text("created_at").notNull().default(now()),
47
+ updatedAt: text("updated_at").notNull().default(now()),
48
+ },
49
+ (space) => [
50
+ uniqueIndex("content_spaces_files_database_unique").on(
51
+ space.filesDatabaseId,
52
+ ),
53
+ index("content_spaces_owner_org_idx").on(space.ownerEmail, space.orgId),
54
+ index("content_spaces_org_idx").on(space.orgId),
55
+ ],
56
+ );
57
+
58
+ export const contentSpaceCatalogItems = table(
59
+ "content_space_catalog_items",
60
+ {
61
+ id: text("id").primaryKey(),
62
+ ownerEmail: text("owner_email").notNull(),
63
+ catalogDatabaseId: text("catalog_database_id").notNull(),
64
+ databaseItemId: text("database_item_id").notNull(),
65
+ documentId: text("document_id").notNull(),
66
+ spaceId: text("space_id").notNull(),
67
+ createdAt: text("created_at").notNull().default(now()),
68
+ updatedAt: text("updated_at").notNull().default(now()),
69
+ },
70
+ (catalogItem) => [
71
+ uniqueIndex("content_space_catalog_items_catalog_space_unique").on(
72
+ catalogItem.catalogDatabaseId,
73
+ catalogItem.spaceId,
74
+ ),
75
+ uniqueIndex("content_space_catalog_items_catalog_item_unique").on(
76
+ catalogItem.catalogDatabaseId,
77
+ catalogItem.databaseItemId,
78
+ ),
79
+ index("content_space_catalog_items_owner_catalog_idx").on(
80
+ catalogItem.ownerEmail,
81
+ catalogItem.catalogDatabaseId,
82
+ ),
83
+ index("content_space_catalog_items_space_idx").on(catalogItem.spaceId),
84
+ ],
85
+ );
86
+
34
87
  export const documentVersions = table("document_versions", {
35
88
  id: text("id").primaryKey(),
36
89
  ownerEmail: text("owner_email").notNull().default("local@localhost"),
@@ -160,47 +213,67 @@ export const documentPropertyDefinitions = table(
160
213
  },
161
214
  );
162
215
 
163
- export const contentDatabases = table("content_databases", {
164
- id: text("id").primaryKey(),
165
- ownerEmail: text("owner_email").notNull().default("local@localhost"),
166
- orgId: text("org_id"),
167
- documentId: text("document_id").notNull(),
168
- ownerDocumentId: text("owner_document_id"),
169
- ownerBlockId: text("owner_block_id"),
170
- title: text("title").notNull().default("Untitled database"),
171
- viewConfigJson: text("view_config_json").notNull().default("{}"),
172
- // Single source of truth for the primary "Content" Blocks field — the one
173
- // backed by `documents.content`. A DB-enforced single-primary invariant: at
174
- // most one property id lives here, so two concurrent seeds can never produce
175
- // two aliasing primaries. NULL means there is currently no primary Blocks
176
- // field (never seeded, or the primary was intentionally deleted).
177
- primaryBlocksPropertyId: text("primary_blocks_property_id"),
178
- // 1 once a database has been seeded with its primary Blocks field at least
179
- // once. Distinguishes "never seeded" (legacy database needing backfill) from
180
- // "primary intentionally deleted" (seeded once, then removed must NOT be
181
- // reseeded). See delete-document-property.
182
- blocksSeeded: integer("blocks_seeded").notNull().default(0),
183
- deletedAt: text("deleted_at"),
184
- createdAt: text("created_at").notNull().default(now()),
185
- updatedAt: text("updated_at").notNull().default(now()),
186
- });
216
+ export const contentDatabases = table(
217
+ "content_databases",
218
+ {
219
+ id: text("id").primaryKey(),
220
+ spaceId: text("space_id"),
221
+ ownerEmail: text("owner_email").notNull().default("local@localhost"),
222
+ orgId: text("org_id"),
223
+ documentId: text("document_id").notNull(),
224
+ ownerDocumentId: text("owner_document_id"),
225
+ ownerBlockId: text("owner_block_id"),
226
+ title: text("title").notNull().default("Untitled database"),
227
+ systemRole: text("system_role"),
228
+ viewConfigJson: text("view_config_json").notNull().default("{}"),
229
+ // Single source of truth for the primary "Content" Blocks field — the one
230
+ // backed by `documents.content`. A DB-enforced single-primary invariant: at
231
+ // most one property id lives here, so two concurrent seeds can never produce
232
+ // two aliasing primaries. NULL means there is currently no primary Blocks
233
+ // field (never seeded, or the primary was intentionally deleted).
234
+ primaryBlocksPropertyId: text("primary_blocks_property_id"),
235
+ // 1 once a database has been seeded with its primary Blocks field at least
236
+ // once. Distinguishes "never seeded" (legacy database needing backfill) from
237
+ // "primary intentionally deleted" (seeded once, then removed — must NOT be
238
+ // reseeded). See delete-document-property.
239
+ blocksSeeded: integer("blocks_seeded").notNull().default(0),
240
+ deletedAt: text("deleted_at"),
241
+ createdAt: text("created_at").notNull().default(now()),
242
+ updatedAt: text("updated_at").notNull().default(now()),
243
+ },
244
+ (database) => [
245
+ uniqueIndex("content_databases_space_system_role_unique").on(
246
+ database.spaceId,
247
+ database.systemRole,
248
+ ),
249
+ ],
250
+ );
187
251
 
188
- export const contentDatabaseItems = table("content_database_items", {
189
- id: text("id").primaryKey(),
190
- ownerEmail: text("owner_email").notNull().default("local@localhost"),
191
- orgId: text("org_id"),
192
- databaseId: text("database_id").notNull(),
193
- documentId: text("document_id").notNull(),
194
- position: integer("position").notNull().default(0),
195
- bodyHydrationStatus: text("body_hydration_status")
196
- .notNull()
197
- .default("hydrated"),
198
- bodyHydrationAttemptedAt: text("body_hydration_attempted_at"),
199
- bodyHydrationError: text("body_hydration_error"),
200
- bodyHydrationVersion: text("body_hydration_version"),
201
- createdAt: text("created_at").notNull().default(now()),
202
- updatedAt: text("updated_at").notNull().default(now()),
203
- });
252
+ export const contentDatabaseItems = table(
253
+ "content_database_items",
254
+ {
255
+ id: text("id").primaryKey(),
256
+ ownerEmail: text("owner_email").notNull().default("local@localhost"),
257
+ orgId: text("org_id"),
258
+ databaseId: text("database_id").notNull(),
259
+ documentId: text("document_id").notNull(),
260
+ position: integer("position").notNull().default(0),
261
+ bodyHydrationStatus: text("body_hydration_status")
262
+ .notNull()
263
+ .default("hydrated"),
264
+ bodyHydrationAttemptedAt: text("body_hydration_attempted_at"),
265
+ bodyHydrationError: text("body_hydration_error"),
266
+ bodyHydrationVersion: text("body_hydration_version"),
267
+ createdAt: text("created_at").notNull().default(now()),
268
+ updatedAt: text("updated_at").notNull().default(now()),
269
+ },
270
+ (item) => [
271
+ uniqueIndex("content_database_items_database_document_unique").on(
272
+ item.databaseId,
273
+ item.documentId,
274
+ ),
275
+ ],
276
+ );
204
277
 
205
278
  export const contentDatabaseBodyHydrationQueue = table(
206
279
  "content_database_body_hydration_queue",
@@ -1,5 +1,5 @@
1
1
  import { resolveAccess } from "@agent-native/core/sharing";
2
- import { and, eq, isNull } from "drizzle-orm";
2
+ import { and, asc, eq, isNull, sql } from "drizzle-orm";
3
3
 
4
4
  import { getDb, schema } from "../db/index.js";
5
5
 
@@ -55,9 +55,23 @@ export async function getDocumentContextPath(
55
55
  eq(schema.contentDatabaseItems.documentId, document.id),
56
56
  isNull(schema.contentDatabases.deletedAt),
57
57
  ),
58
+ )
59
+ .orderBy(
60
+ sql`CASE WHEN ${schema.contentDatabases.systemRole} IS NULL THEN 0 ELSE 1 END`,
61
+ asc(schema.contentDatabases.id),
62
+ );
63
+ const [backingDatabase] = await db
64
+ .select({ id: schema.contentDatabases.id })
65
+ .from(schema.contentDatabases)
66
+ .where(
67
+ and(
68
+ eq(schema.contentDatabases.documentId, document.id),
69
+ isNull(schema.contentDatabases.deletedAt),
70
+ ),
58
71
  );
59
72
  if (
60
73
  membership &&
74
+ !(membership.database.systemRole && backingDatabase) &&
61
75
  !path.some((entry) => entry.id === membership.database.id)
62
76
  ) {
63
77
  const databaseDocumentAccess = await resolveAccess(
@@ -5,6 +5,7 @@ import crypto from "node:crypto";
5
5
  import { and, eq, inArray, isNull, lt, or } from "drizzle-orm";
6
6
  import type { InferSelectModel } from "drizzle-orm";
7
7
 
8
+ import { ensureDocumentFilesMembership } from "../../actions/_content-files.js";
8
9
  import type { DocumentSyncStatus } from "../../shared/api.js";
9
10
  import { canonicalizeNfm, nfmToDoc, type PMNode } from "../../shared/nfm.js";
10
11
  import { getDb, schema } from "../db/index.js";
@@ -492,11 +493,15 @@ async function createLinkedChildDocument(args: {
492
493
  const db = getDb();
493
494
  const now = nowIso();
494
495
  const id = nanoid();
496
+ if (!args.parent.spaceId) {
497
+ throw new Error("Parent document does not belong to a Content space.");
498
+ }
495
499
 
496
500
  let inserted = false;
497
501
  try {
498
502
  await db.insert(schema.documents).values({
499
503
  id,
504
+ spaceId: args.parent.spaceId,
500
505
  ownerEmail: args.parent.ownerEmail,
501
506
  orgId: args.parent.orgId,
502
507
  parentId: args.parent.id,
@@ -511,6 +516,7 @@ async function createLinkedChildDocument(args: {
511
516
  updatedAt: now,
512
517
  });
513
518
  inserted = true;
519
+ await ensureDocumentFilesMembership(db, id, now);
514
520
  await inheritShares(args.parent.id, id, now);
515
521
  await upsertSyncLink({
516
522
  owner: args.owner,
@@ -694,6 +694,159 @@ const runContentMigrations = runMigrations(
694
694
  owner_email
695
695
  )`,
696
696
  },
697
+ {
698
+ version: 70,
699
+ name: "content-spaces-table",
700
+ sql: `CREATE TABLE IF NOT EXISTS content_spaces (
701
+ id TEXT PRIMARY KEY,
702
+ name TEXT NOT NULL,
703
+ kind TEXT NOT NULL,
704
+ owner_email TEXT NOT NULL,
705
+ org_id TEXT,
706
+ files_database_id TEXT NOT NULL,
707
+ created_by TEXT NOT NULL,
708
+ archived_at TEXT,
709
+ created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
710
+ updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
711
+ )`,
712
+ },
713
+ {
714
+ version: 71,
715
+ name: "content-space-catalog-items-table",
716
+ sql: `CREATE TABLE IF NOT EXISTS content_space_catalog_items (
717
+ id TEXT PRIMARY KEY,
718
+ owner_email TEXT NOT NULL,
719
+ catalog_database_id TEXT NOT NULL,
720
+ database_item_id TEXT NOT NULL,
721
+ document_id TEXT NOT NULL,
722
+ space_id TEXT NOT NULL,
723
+ created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
724
+ updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
725
+ )`,
726
+ },
727
+ {
728
+ version: 72,
729
+ name: "content-space-columns",
730
+ sql: `ALTER TABLE documents ADD COLUMN IF NOT EXISTS space_id TEXT;
731
+ ALTER TABLE content_databases ADD COLUMN IF NOT EXISTS space_id TEXT;
732
+ ALTER TABLE content_databases ADD COLUMN IF NOT EXISTS system_role TEXT`,
733
+ },
734
+ {
735
+ version: 73,
736
+ name: "content-space-hot-path-indexes",
737
+ sql: `CREATE UNIQUE INDEX IF NOT EXISTS content_spaces_files_database_unique ON content_spaces (files_database_id);
738
+ CREATE INDEX IF NOT EXISTS content_spaces_owner_org_idx ON content_spaces (owner_email, org_id);
739
+ CREATE INDEX IF NOT EXISTS content_spaces_org_idx ON content_spaces (org_id);
740
+ CREATE UNIQUE INDEX IF NOT EXISTS content_space_catalog_items_catalog_space_unique ON content_space_catalog_items (catalog_database_id, space_id);
741
+ CREATE UNIQUE INDEX IF NOT EXISTS content_space_catalog_items_catalog_item_unique ON content_space_catalog_items (catalog_database_id, database_item_id);
742
+ CREATE INDEX IF NOT EXISTS content_space_catalog_items_owner_catalog_idx ON content_space_catalog_items (owner_email, catalog_database_id);
743
+ CREATE INDEX IF NOT EXISTS content_space_catalog_items_space_idx ON content_space_catalog_items (space_id);
744
+ CREATE INDEX IF NOT EXISTS documents_space_idx ON documents (space_id);
745
+ CREATE INDEX IF NOT EXISTS content_databases_space_idx ON content_databases (space_id);
746
+ CREATE UNIQUE INDEX IF NOT EXISTS content_databases_space_system_role_unique ON content_databases (space_id, system_role)`,
747
+ },
748
+ {
749
+ version: 74,
750
+ name: "content-database-items-canonical-membership",
751
+ sql: `DROP INDEX IF EXISTS content_space_catalog_items_catalog_item_unique;
752
+ DROP INDEX IF EXISTS content_database_body_hydration_queue_item_idx;
753
+ UPDATE content_space_catalog_items
754
+ SET database_item_id = (
755
+ SELECT MIN(canonical.id)
756
+ FROM content_database_items original
757
+ INNER JOIN content_database_items canonical
758
+ ON canonical.database_id = original.database_id
759
+ AND canonical.document_id = original.document_id
760
+ WHERE original.id = content_space_catalog_items.database_item_id
761
+ )
762
+ WHERE EXISTS (
763
+ SELECT 1
764
+ FROM content_database_items original
765
+ INNER JOIN content_database_items canonical
766
+ ON canonical.database_id = original.database_id
767
+ AND canonical.document_id = original.document_id
768
+ WHERE original.id = content_space_catalog_items.database_item_id
769
+ AND canonical.id < original.id
770
+ );
771
+ UPDATE content_database_body_hydration_queue
772
+ SET database_item_id = (
773
+ SELECT MIN(canonical.id)
774
+ FROM content_database_items original
775
+ INNER JOIN content_database_items canonical
776
+ ON canonical.database_id = original.database_id
777
+ AND canonical.document_id = original.document_id
778
+ WHERE original.id = content_database_body_hydration_queue.database_item_id
779
+ )
780
+ WHERE EXISTS (
781
+ SELECT 1
782
+ FROM content_database_items original
783
+ INNER JOIN content_database_items canonical
784
+ ON canonical.database_id = original.database_id
785
+ AND canonical.document_id = original.document_id
786
+ WHERE original.id = content_database_body_hydration_queue.database_item_id
787
+ AND canonical.id < original.id
788
+ );
789
+ UPDATE content_database_source_rows
790
+ SET database_item_id = (
791
+ SELECT MIN(canonical.id)
792
+ FROM content_database_items original
793
+ INNER JOIN content_database_items canonical
794
+ ON canonical.database_id = original.database_id
795
+ AND canonical.document_id = original.document_id
796
+ WHERE original.id = content_database_source_rows.database_item_id
797
+ )
798
+ WHERE EXISTS (
799
+ SELECT 1
800
+ FROM content_database_items original
801
+ INNER JOIN content_database_items canonical
802
+ ON canonical.database_id = original.database_id
803
+ AND canonical.document_id = original.document_id
804
+ WHERE original.id = content_database_source_rows.database_item_id
805
+ AND canonical.id < original.id
806
+ );
807
+ UPDATE content_database_source_change_sets
808
+ SET database_item_id = (
809
+ SELECT MIN(canonical.id)
810
+ FROM content_database_items original
811
+ INNER JOIN content_database_items canonical
812
+ ON canonical.database_id = original.database_id
813
+ AND canonical.document_id = original.document_id
814
+ WHERE original.id = content_database_source_change_sets.database_item_id
815
+ )
816
+ WHERE EXISTS (
817
+ SELECT 1
818
+ FROM content_database_items original
819
+ INNER JOIN content_database_items canonical
820
+ ON canonical.database_id = original.database_id
821
+ AND canonical.document_id = original.document_id
822
+ WHERE original.id = content_database_source_change_sets.database_item_id
823
+ AND canonical.id < original.id
824
+ );
825
+ DELETE FROM content_space_catalog_items
826
+ WHERE id NOT IN (
827
+ SELECT MIN(id)
828
+ FROM content_space_catalog_items
829
+ GROUP BY catalog_database_id, database_item_id
830
+ );
831
+ DELETE FROM content_database_body_hydration_queue
832
+ WHERE id NOT IN (
833
+ SELECT MIN(id)
834
+ FROM content_database_body_hydration_queue
835
+ GROUP BY database_item_id
836
+ );
837
+ CREATE UNIQUE INDEX IF NOT EXISTS content_space_catalog_items_catalog_item_unique
838
+ ON content_space_catalog_items (catalog_database_id, database_item_id);
839
+ CREATE UNIQUE INDEX IF NOT EXISTS content_database_body_hydration_queue_item_idx
840
+ ON content_database_body_hydration_queue (database_item_id);
841
+ DELETE FROM content_database_items
842
+ WHERE id NOT IN (
843
+ SELECT MIN(id)
844
+ FROM content_database_items
845
+ GROUP BY database_id, document_id
846
+ );
847
+ CREATE UNIQUE INDEX IF NOT EXISTS content_database_items_database_document_unique
848
+ ON content_database_items (database_id, document_id)`,
849
+ },
697
850
  ],
698
851
  { table: "content_migrations" },
699
852
  );
@@ -96,6 +96,7 @@ export interface ResolveDocumentSyncConflictRequest {
96
96
 
97
97
  export interface DocumentCreateRequest {
98
98
  id?: string;
99
+ spaceId?: string;
99
100
  title?: string;
100
101
  parentId?: string | null;
101
102
  content?: string;
@@ -289,7 +290,8 @@ export type ContentDatabaseViewType =
289
290
  | "gallery"
290
291
  | "calendar"
291
292
  | "timeline"
292
- | "form";
293
+ | "form"
294
+ | "sidebar";
293
295
 
294
296
  export type ContentDatabaseRowDensity = "compact" | "default" | "comfortable";
295
297
  export type ContentDatabaseFilterMode = "and" | "or";
@@ -414,7 +416,12 @@ export type ContentDatabaseSourceType =
414
416
  | "mock-local"
415
417
  | "builder-cms"
416
418
  | "local-table"
417
- | "notion-database";
419
+ | "notion-database"
420
+ | "local-folder";
421
+ export type ContentDatabaseSourceTruthPolicy =
422
+ | "database_primary"
423
+ | "source_primary"
424
+ | "reviewed_bidirectional";
418
425
  export type ContentDatabaseSourceSyncState =
419
426
  | "idle"
420
427
  | "linked"
@@ -433,7 +440,7 @@ export type ContentDatabaseSourceWriteMode =
433
440
  | "publish_updates";
434
441
  export type BuilderCmsPublicationTransitionIntent = "publish" | "unpublish";
435
442
  export const BUILDER_CMS_SAFE_WRITE_MODEL = "agent-native-blog-article-test";
436
- export type ContentDatabaseSourceChangeDirection = "outbound";
443
+ export type ContentDatabaseSourceChangeDirection = "incoming" | "outbound";
437
444
  export type ContentDatabaseSourceChangeState =
438
445
  | "proposed"
439
446
  | "pending_push"
@@ -471,6 +478,9 @@ export interface ContentDatabaseSourceCapabilities {
471
478
  canStageLocalRevision: boolean;
472
479
  liveWritesEnabled: boolean;
473
480
  readOnlyRefresh: boolean;
481
+ canRename?: boolean;
482
+ canReveal?: boolean;
483
+ canUseLocalComponents?: boolean;
474
484
  }
475
485
 
476
486
  export interface ContentDatabaseSourceFieldMapping {
@@ -640,6 +650,9 @@ export interface ContentDatabaseSource {
640
650
  allowPublicationTransitions?: boolean;
641
651
  notes?: string | null;
642
652
  readMode?: "fixture" | "builder-api" | string | null;
653
+ connectionId?: string | null;
654
+ connectionLabel?: string | null;
655
+ truthPolicy?: ContentDatabaseSourceTruthPolicy;
643
656
  liveReadConfigured?: boolean;
644
657
  lastReadEntryCount?: number;
645
658
  lastReadMatchedRowCount?: number;
@@ -764,6 +777,7 @@ export interface ContentDatabaseSourceFieldPropertyResponse {
764
777
 
765
778
  export interface CreateDatabaseRequest {
766
779
  documentId?: string;
780
+ spaceId?: string;
767
781
  parentId?: string | null;
768
782
  title?: string;
769
783
  description?: string;