@agent-native/core 0.102.1 → 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 (295) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +15 -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/client/AgentPanel.tsx +7 -0
  31. package/corpus/core/src/client/AssistantChat.tsx +7 -0
  32. package/corpus/core/src/client/agent-chat-adapter.ts +7 -1
  33. package/corpus/core/src/client/chat/message-components.tsx +17 -3
  34. package/corpus/core/src/client/composer/ComposerPlusMenu.tsx +96 -6
  35. package/corpus/core/src/client/composer/asset-picker-url.ts +80 -0
  36. package/corpus/core/src/client/error-format.ts +24 -0
  37. package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +8 -1
  38. package/corpus/core/src/local-artifacts/index.ts +65 -0
  39. package/corpus/templates/assets/app/components/library/GenerationPresetsPanel.tsx +325 -0
  40. package/corpus/templates/assets/app/hooks/use-navigation-state.ts +12 -0
  41. package/corpus/templates/assets/app/i18n/zh-TW.ts +21 -0
  42. package/corpus/templates/assets/app/i18n-data.ts +215 -0
  43. package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +19 -479
  44. package/corpus/templates/assets/app/routes/brand-kits.$id_.presets.$presetId.tsx +1 -1
  45. package/corpus/templates/assets/app/routes/brand-kits.$id_.settings.tsx +446 -0
  46. package/corpus/templates/assets/app/routes/library.tsx +69 -0
  47. package/corpus/templates/assets/changelog/2026-07-15-fixed-top-level-image-picker-selections-returning-to-the-com.md +6 -0
  48. package/corpus/templates/clips/actions/disconnect-calendar.ts +57 -9
  49. package/corpus/templates/clips/actions/generate-workflow.ts +102 -59
  50. package/corpus/templates/clips/actions/get-recording-player-data.ts +64 -1
  51. package/corpus/templates/clips/actions/regenerate-summary.ts +7 -0
  52. package/corpus/templates/clips/actions/regenerate-title.ts +29 -11
  53. package/corpus/templates/clips/app/components/editor/editor-layout.tsx +34 -13
  54. package/corpus/templates/clips/app/components/editor/thumbnail-picker.tsx +87 -9
  55. package/corpus/templates/clips/app/components/editor/trim-handles.tsx +15 -0
  56. package/corpus/templates/clips/app/components/editor/waveform.tsx +21 -8
  57. package/corpus/templates/clips/app/components/library/folder-tree.tsx +52 -0
  58. package/corpus/templates/clips/app/components/player/settings-panel.tsx +116 -58
  59. package/corpus/templates/clips/app/components/player/share-dialog.tsx +43 -37
  60. package/corpus/templates/clips/app/components/player/video-player.tsx +50 -2
  61. package/corpus/templates/clips/app/components/recorder/microphone-visualizer.tsx +22 -3
  62. package/corpus/templates/clips/app/i18n/ar-SA.ts +5 -2
  63. package/corpus/templates/clips/app/i18n/de-DE.ts +6 -2
  64. package/corpus/templates/clips/app/i18n/en-US.ts +5 -2
  65. package/corpus/templates/clips/app/i18n/es-ES.ts +6 -2
  66. package/corpus/templates/clips/app/i18n/fr-FR.ts +5 -2
  67. package/corpus/templates/clips/app/i18n/hi-IN.ts +5 -2
  68. package/corpus/templates/clips/app/i18n/ja-JP.ts +6 -1
  69. package/corpus/templates/clips/app/i18n/ko-KR.ts +5 -2
  70. package/corpus/templates/clips/app/i18n/pt-BR.ts +6 -2
  71. package/corpus/templates/clips/app/i18n/zh-CN.ts +5 -2
  72. package/corpus/templates/clips/app/i18n/zh-TW.ts +5 -2
  73. package/corpus/templates/clips/app/lib/timestamp-mapping.ts +14 -0
  74. package/corpus/templates/clips/app/routes/_app.library._index.tsx +1 -2
  75. package/corpus/templates/clips/app/routes/_index.tsx +1 -2
  76. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +98 -32
  77. package/corpus/templates/clips/app/routes/share.$shareId.tsx +4 -1
  78. package/corpus/templates/clips/changelog/2026-07-15-ai-workflow-generation-now-stays-visible-avoids-duplicate-re.md +6 -0
  79. package/corpus/templates/clips/changelog/2026-07-15-clip-playback-and-cta-controls-remain-interactive-through-ed.md +6 -0
  80. package/corpus/templates/clips/changelog/2026-07-15-clip-titles-no-longer-describe-the-product-as-a-loom-alterna.md +6 -0
  81. package/corpus/templates/clips/changelog/2026-07-15-description-regeneration-now-opens-the-agent-chat-so-progres.md +6 -0
  82. package/corpus/templates/clips/changelog/2026-07-15-direct-recording-urls-now-respect-share-link-and-password-ac.md +6 -0
  83. package/corpus/templates/clips/changelog/2026-07-15-disconnecting-a-calendar-now-clears-unrecorded-synced-meetin.md +6 -0
  84. package/corpus/templates/clips/changelog/2026-07-15-folders-now-expose-rename-and-delete-actions-directly-in-the.md +6 -0
  85. package/corpus/templates/clips/changelog/2026-07-15-recording-pages-now-explain-sign-in-access-and-avoid-showing.md +6 -0
  86. package/corpus/templates/clips/changelog/2026-07-15-the-clips-extension-quick-actions-toolbar-can-be-moved-out-o.md +6 -0
  87. package/corpus/templates/clips/changelog/2026-07-15-the-editor-now-skips-cut-sections-during-preview-and-keeps-t.md +6 -0
  88. package/corpus/templates/clips/changelog/2026-07-15-thumbnail-capture-now-updates-previews-while-scrubbing-and-l.md +6 -0
  89. package/corpus/templates/clips/changelog/2026-07-15-windows-permission-links-open-the-matching-settings-page.md +6 -0
  90. package/corpus/templates/clips/chrome-extension/src/content-script.ts +117 -2
  91. package/corpus/templates/clips/chrome-extension/src/overlay.ts +27 -0
  92. package/corpus/templates/clips/desktop/src-tauri/tauri.conf.json +1 -1
  93. package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +139 -101
  94. package/corpus/templates/clips/server/lib/recording-page-access.ts +35 -0
  95. package/corpus/templates/clips/server/lib/share-password.ts +6 -3
  96. package/corpus/templates/content/.agents/skills/content/SKILL.md +26 -39
  97. package/corpus/templates/content/AGENTS.md +25 -30
  98. package/corpus/templates/content/actions/_builder-docs-client.ts +23 -0
  99. package/corpus/templates/content/actions/_content-database-source-adapters.ts +21 -3
  100. package/corpus/templates/content/actions/_content-files.ts +338 -0
  101. package/corpus/templates/content/actions/_content-space-access.ts +135 -0
  102. package/corpus/templates/content/actions/_content-spaces.ts +640 -0
  103. package/corpus/templates/content/actions/_database-source-utils.ts +90 -7
  104. package/corpus/templates/content/actions/_database-utils.ts +7 -1
  105. package/corpus/templates/content/actions/_local-file-documents.ts +0 -9
  106. package/corpus/templates/content/actions/_local-folder-source.ts +53 -0
  107. package/corpus/templates/content/actions/_property-utils.ts +9 -4
  108. package/corpus/templates/content/actions/add-database-item.ts +108 -65
  109. package/corpus/templates/content/actions/backfill-content-files.ts +22 -0
  110. package/corpus/templates/content/actions/connect-local-folder-source.ts +221 -0
  111. package/corpus/templates/content/actions/create-content-database.ts +129 -3
  112. package/corpus/templates/content/actions/create-document.ts +65 -55
  113. package/corpus/templates/content/actions/create-inline-content-database.ts +6 -1
  114. package/corpus/templates/content/actions/delete-content-database.ts +3 -0
  115. package/corpus/templates/content/actions/delete-document.ts +7 -11
  116. package/corpus/templates/content/actions/disconnect-local-folder-source.ts +175 -0
  117. package/corpus/templates/content/actions/duplicate-database-item.ts +10 -0
  118. package/corpus/templates/content/actions/duplicate-database-items.ts +13 -0
  119. package/corpus/templates/content/actions/edit-document.ts +2 -28
  120. package/corpus/templates/content/actions/ensure-content-spaces.ts +26 -0
  121. package/corpus/templates/content/actions/export-content-source.ts +47 -9
  122. package/corpus/templates/content/actions/get-document.ts +0 -14
  123. package/corpus/templates/content/actions/import-content-source.ts +43 -3
  124. package/corpus/templates/content/actions/list-content-spaces.ts +103 -0
  125. package/corpus/templates/content/actions/list-documents.ts +12 -9
  126. package/corpus/templates/content/actions/move-document.ts +3 -14
  127. package/corpus/templates/content/actions/pull-document.ts +0 -23
  128. package/corpus/templates/content/actions/remove-local-file-source.ts +50 -29
  129. package/corpus/templates/content/actions/resolve-local-folder-conflict.ts +442 -0
  130. package/corpus/templates/content/actions/reveal-local-source-file.ts +6 -17
  131. package/corpus/templates/content/actions/search-documents.ts +0 -34
  132. package/corpus/templates/content/actions/share-local-file-document.ts +25 -1
  133. package/corpus/templates/content/actions/submit-content-database-form.ts +12 -0
  134. package/corpus/templates/content/actions/sync-local-folder-source.ts +731 -0
  135. package/corpus/templates/content/actions/sync-manifest-local-folder-source.ts +123 -0
  136. package/corpus/templates/content/actions/update-content-database-view.ts +10 -1
  137. package/corpus/templates/content/actions/update-document.ts +0 -15
  138. package/corpus/templates/content/actions/view-screen.ts +2 -50
  139. package/corpus/templates/content/app/components/editor/SlashCommandMenu.tsx +76 -62
  140. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +70 -22
  141. package/corpus/templates/content/app/components/editor/database/grouping.ts +2 -1
  142. package/corpus/templates/content/app/components/editor/database/settings.tsx +23 -20
  143. package/corpus/templates/content/app/components/editor/database/shared.tsx +2 -0
  144. package/corpus/templates/content/app/components/editor/database/sidebar.tsx +330 -0
  145. package/corpus/templates/content/app/components/editor/database/types.ts +1 -0
  146. package/corpus/templates/content/app/components/editor/database/view-config.ts +3 -1
  147. package/corpus/templates/content/app/components/layout/Layout.tsx +25 -1
  148. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +209 -113
  149. package/corpus/templates/content/app/components/sidebar/select-content-space.ts +31 -0
  150. package/corpus/templates/content/app/hooks/use-content-database.ts +16 -0
  151. package/corpus/templates/content/app/hooks/use-content-spaces.ts +39 -0
  152. package/corpus/templates/content/app/i18n/zh-TW.ts +11 -0
  153. package/corpus/templates/content/app/i18n-data.ts +75 -0
  154. package/corpus/templates/content/app/routes/_app.local-files.tsx +174 -65
  155. package/corpus/templates/content/changelog/2026-07-16-content-callouts-can-now-be-reviewed-and-published-to-builder.md +6 -0
  156. package/corpus/templates/content/changelog/2026-07-16-heading-5-and-heading-6-are-available-from-the-editor-slash-.md +6 -0
  157. package/corpus/templates/content/changelog/2026-07-16-organize-every-workspace-through-a-customizable-files-databa.md +6 -0
  158. package/corpus/templates/content/parity/matrix.md +2 -1
  159. package/corpus/templates/content/parity/matrix.ts +37 -1
  160. package/corpus/templates/content/scripts/dev-database.mjs +7 -5
  161. package/corpus/templates/content/server/db/schema.ts +113 -40
  162. package/corpus/templates/content/server/lib/document-context.ts +15 -1
  163. package/corpus/templates/content/server/lib/notion-sync.ts +6 -0
  164. package/corpus/templates/content/server/plugins/db.ts +153 -0
  165. package/corpus/templates/content/shared/api.ts +17 -3
  166. package/corpus/templates/content/shared/builder-mdx.ts +163 -16
  167. package/corpus/templates/design/.agents/skills/design-templates/SKILL.md +59 -0
  168. package/corpus/templates/design/AGENTS.md +6 -1
  169. package/corpus/templates/design/actions/create-design-from-template.ts +19 -7
  170. package/corpus/templates/design/actions/list-design-templates.ts +69 -21
  171. package/corpus/templates/design/actions/navigate.ts +2 -2
  172. package/corpus/templates/design/actions/view-screen.ts +15 -2
  173. package/corpus/templates/design/agent-native.app-skill.json +5 -0
  174. package/corpus/templates/design/app/components/design/design-canvas/external-preview.ts +7 -3
  175. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +281 -56
  176. package/corpus/templates/design/app/components/templates/TemplatePreview.tsx +14 -2
  177. package/corpus/templates/design/app/hooks/use-navigation-state.ts +3 -2
  178. package/corpus/templates/design/app/i18n/zh-TW.ts +3 -3
  179. package/corpus/templates/design/app/i18n-data.ts +21 -2
  180. package/corpus/templates/design/app/i18n-template-feature.ts +218 -10
  181. package/corpus/templates/design/app/pages/Index.tsx +195 -24
  182. package/corpus/templates/design/app/pages/Templates.tsx +144 -55
  183. package/corpus/templates/design/app/pages/design-editor/generation-prompt-directives.ts +12 -1
  184. package/corpus/templates/design/changelog/2026-07-14-templates-now-appear-in-the-new-design-picker-with-previews-.md +6 -0
  185. package/corpus/templates/design/changelog/2026-07-15-prototype-print-and-download-buttons-now-work-in-preview.md +6 -0
  186. package/corpus/templates/design/changelog/2026-07-15-templates-now-open-immediately-after-copying-even-while-the-.md +6 -0
  187. package/corpus/templates/design/server/plugins/agent-chat.ts +1 -1
  188. package/corpus/templates/mail/AGENTS.md +23 -18
  189. package/corpus/templates/mail/actions/bulk-archive.ts +32 -28
  190. package/corpus/templates/mail/actions/mark-read.ts +131 -20
  191. package/corpus/templates/mail/actions/mark-thread-read.ts +1 -1
  192. package/corpus/templates/mail/actions/move-email.ts +30 -24
  193. package/corpus/templates/mail/actions/send-email.ts +73 -68
  194. package/corpus/templates/mail/changelog/2026-07-15-unread-inbox-cleanup-now-completes-reliably.md +6 -0
  195. package/corpus/templates/mail/server/handlers/emails.ts +218 -209
  196. package/corpus/templates/mail/server/lib/bulk-mark-read.ts +30 -0
  197. package/corpus/templates/mail/server/lib/email-state.ts +198 -113
  198. package/corpus/templates/mail/server/lib/google-auth.ts +218 -25
  199. package/corpus/templates/mail/server/lib/jobs.ts +69 -74
  200. package/corpus/templates/mail/server/lib/local-email-store.ts +265 -0
  201. package/corpus/templates/mail/server/plugins/agent-chat.ts +6 -0
  202. package/corpus/templates/slides/actions/extract-pdf.ts +1 -1
  203. package/corpus/templates/slides/actions/import-file.ts +4 -1
  204. package/corpus/templates/slides/app/components/editor/ImageGenPanel.tsx +1 -1
  205. package/corpus/templates/slides/app/components/editor/ImageSearchPanel.tsx +9 -12
  206. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +29 -21
  207. package/corpus/templates/slides/app/i18n/ar-SA.ts +1 -0
  208. package/corpus/templates/slides/app/i18n/de-DE.ts +1 -0
  209. package/corpus/templates/slides/app/i18n/en-US.ts +1 -0
  210. package/corpus/templates/slides/app/i18n/es-ES.ts +1 -0
  211. package/corpus/templates/slides/app/i18n/fr-FR.ts +1 -0
  212. package/corpus/templates/slides/app/i18n/hi-IN.ts +1 -0
  213. package/corpus/templates/slides/app/i18n/ja-JP.ts +1 -0
  214. package/corpus/templates/slides/app/i18n/ko-KR.ts +1 -0
  215. package/corpus/templates/slides/app/i18n/pt-BR.ts +1 -0
  216. package/corpus/templates/slides/app/i18n/zh-CN.ts +1 -0
  217. package/corpus/templates/slides/app/i18n/zh-TW.ts +1 -0
  218. package/corpus/templates/slides/changelog/2026-07-15-image-search-and-generation-controls-now-use-the-registered-.md +6 -0
  219. package/corpus/templates/slides/changelog/2026-07-15-pdf-deck-references-can-be-imported-for-slide-inspiration-ag.md +6 -0
  220. package/corpus/templates/slides/changelog/2026-07-15-stable-style-inspector-dock.md +6 -0
  221. package/dist/cli/content-local.d.ts +1 -0
  222. package/dist/cli/content-local.d.ts.map +1 -1
  223. package/dist/cli/content-local.js +75 -17
  224. package/dist/cli/content-local.js.map +1 -1
  225. package/dist/cli/index.js +2 -2
  226. package/dist/cli/index.js.map +1 -1
  227. package/dist/cli/skills-content/content-skill.d.ts +1 -1
  228. package/dist/cli/skills-content/content-skill.d.ts.map +1 -1
  229. package/dist/cli/skills-content/content-skill.js +36 -25
  230. package/dist/cli/skills-content/content-skill.js.map +1 -1
  231. package/dist/cli/skills.d.ts.map +1 -1
  232. package/dist/cli/skills.js +47 -14
  233. package/dist/cli/skills.js.map +1 -1
  234. package/dist/client/AgentPanel.d.ts.map +1 -1
  235. package/dist/client/AgentPanel.js +5 -0
  236. package/dist/client/AgentPanel.js.map +1 -1
  237. package/dist/client/AssistantChat.d.ts.map +1 -1
  238. package/dist/client/AssistantChat.js +7 -0
  239. package/dist/client/AssistantChat.js.map +1 -1
  240. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  241. package/dist/client/agent-chat-adapter.js +8 -1
  242. package/dist/client/agent-chat-adapter.js.map +1 -1
  243. package/dist/client/chat/message-components.d.ts +4 -0
  244. package/dist/client/chat/message-components.d.ts.map +1 -1
  245. package/dist/client/chat/message-components.js +10 -3
  246. package/dist/client/chat/message-components.js.map +1 -1
  247. package/dist/client/composer/ComposerPlusMenu.d.ts.map +1 -1
  248. package/dist/client/composer/ComposerPlusMenu.js +58 -6
  249. package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
  250. package/dist/client/composer/asset-picker-url.d.ts +16 -0
  251. package/dist/client/composer/asset-picker-url.d.ts.map +1 -0
  252. package/dist/client/composer/asset-picker-url.js +64 -0
  253. package/dist/client/composer/asset-picker-url.js.map +1 -0
  254. package/dist/client/error-format.d.ts.map +1 -1
  255. package/dist/client/error-format.js +17 -0
  256. package/dist/client/error-format.js.map +1 -1
  257. package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
  258. package/dist/client/resources/McpIntegrationDialog.js +6 -1
  259. package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
  260. package/dist/collab/awareness.d.ts +2 -2
  261. package/dist/collab/awareness.d.ts.map +1 -1
  262. package/dist/collab/struct-routes.d.ts +1 -1
  263. package/dist/local-artifacts/index.d.ts +10 -0
  264. package/dist/local-artifacts/index.d.ts.map +1 -1
  265. package/dist/local-artifacts/index.js +39 -0
  266. package/dist/local-artifacts/index.js.map +1 -1
  267. package/dist/notifications/routes.d.ts +1 -1
  268. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  269. package/dist/resources/handlers.d.ts +3 -3
  270. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  271. package/dist/server/transcribe-voice.d.ts +1 -1
  272. package/docs/content/local-file-mode.mdx +99 -489
  273. package/docs/content/locales/ar-SA/local-file-mode.mdx +35 -490
  274. package/docs/content/locales/ar-SA/template-content.mdx +10 -24
  275. package/docs/content/locales/de-DE/local-file-mode.mdx +37 -491
  276. package/docs/content/locales/de-DE/template-content.mdx +10 -24
  277. package/docs/content/locales/es-ES/local-file-mode.mdx +35 -493
  278. package/docs/content/locales/es-ES/template-content.mdx +10 -24
  279. package/docs/content/locales/fr-FR/local-file-mode.mdx +38 -491
  280. package/docs/content/locales/fr-FR/template-content.mdx +10 -24
  281. package/docs/content/locales/hi-IN/local-file-mode.mdx +33 -492
  282. package/docs/content/locales/hi-IN/template-content.mdx +10 -24
  283. package/docs/content/locales/ja-JP/local-file-mode.mdx +36 -492
  284. package/docs/content/locales/ja-JP/template-content.mdx +10 -24
  285. package/docs/content/locales/ko-KR/local-file-mode.mdx +35 -490
  286. package/docs/content/locales/ko-KR/template-content.mdx +10 -24
  287. package/docs/content/locales/pt-BR/local-file-mode.mdx +35 -493
  288. package/docs/content/locales/pt-BR/template-content.mdx +10 -24
  289. package/docs/content/locales/zh-CN/local-file-mode.mdx +31 -489
  290. package/docs/content/locales/zh-CN/template-content.mdx +9 -24
  291. package/docs/content/locales/zh-TW/local-file-mode.mdx +31 -489
  292. package/docs/content/locales/zh-TW/template-content.mdx +9 -24
  293. package/docs/content/template-content.mdx +26 -42
  294. package/package.json +1 -1
  295. package/corpus/templates/assets/app/components/library/EditLibraryDialog.tsx +0 -126
@@ -0,0 +1,446 @@
1
+ import {
2
+ sendToAgentChat,
3
+ useActionMutation,
4
+ useActionQuery,
5
+ useT,
6
+ } from "@agent-native/core/client";
7
+ import {
8
+ useSetHeaderActions,
9
+ useSetPageTitle,
10
+ } from "@agent-native/toolkit/app-shell";
11
+ import {
12
+ IconArrowLeft,
13
+ IconBulb,
14
+ IconChevronDown,
15
+ IconChevronRight,
16
+ IconListCheck,
17
+ IconPhoto,
18
+ IconTextCaption,
19
+ } from "@tabler/icons-react";
20
+ import { useCallback, useEffect, useMemo, useState } from "react";
21
+ import {
22
+ useBeforeUnload,
23
+ useBlocker,
24
+ useNavigate,
25
+ useParams,
26
+ } from "react-router";
27
+ import { toast } from "sonner";
28
+
29
+ import { GenerationPresetsPanel } from "@/components/library/GenerationPresetsPanel";
30
+ import { Badge } from "@/components/ui/badge";
31
+ import { Button } from "@/components/ui/button";
32
+ import {
33
+ Dialog,
34
+ DialogContent,
35
+ DialogDescription,
36
+ DialogFooter,
37
+ DialogHeader,
38
+ DialogTitle,
39
+ } from "@/components/ui/dialog";
40
+ import { Input } from "@/components/ui/input";
41
+ import { Label } from "@/components/ui/label";
42
+ import { Textarea } from "@/components/ui/textarea";
43
+ import { getLibraryCustomInstructions } from "@/lib/libraries";
44
+
45
+ function paletteDraftFromColors(colors: unknown): string {
46
+ return Array.isArray(colors)
47
+ ? colors
48
+ .filter((color) => typeof color === "string")
49
+ .map((color) => color.toLowerCase())
50
+ .join(", ")
51
+ : "";
52
+ }
53
+
54
+ function parsePaletteDraft(value: string): string[] {
55
+ const seen = new Set<string>();
56
+ const colors: string[] = [];
57
+ for (const raw of value.split(/[\s,]+/)) {
58
+ const trimmed = raw.trim();
59
+ if (!trimmed) continue;
60
+ const color = trimmed.startsWith("#") ? trimmed : `#${trimmed}`;
61
+ if (!/^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i.test(color)) continue;
62
+ const normalized = color.toLowerCase();
63
+ if (seen.has(normalized)) continue;
64
+ seen.add(normalized);
65
+ colors.push(normalized);
66
+ }
67
+ return colors;
68
+ }
69
+
70
+ export default function BrandKitSettingsRoute() {
71
+ const t = useT();
72
+ const navigate = useNavigate();
73
+ const { id } = useParams();
74
+ const libraryId = id ?? "";
75
+ const { data } = useActionQuery("get-library", { id: libraryId }) as any;
76
+ const { data: presetData } = useActionQuery("list-generation-presets", {
77
+ libraryId,
78
+ }) as any;
79
+ const updateLibrary = useActionMutation("update-library");
80
+
81
+ const library = data?.library;
82
+ const assets = (data?.assets ?? []) as any[];
83
+ const generationPresets = ((presetData as any)?.presets ?? []) as any[];
84
+
85
+ const [titleDraft, setTitleDraft] = useState("");
86
+ const [descriptionDraft, setDescriptionDraft] = useState("");
87
+ const [styleDescriptionDraft, setStyleDescriptionDraft] = useState("");
88
+ const [customInstructionsDraft, setCustomInstructionsDraft] = useState("");
89
+ const [paletteDraft, setPaletteDraft] = useState("");
90
+ const [detailsOpen, setDetailsOpen] = useState(false);
91
+ const [initializedLibraryId, setInitializedLibraryId] = useState<
92
+ string | null
93
+ >(null);
94
+
95
+ const isDirty = useMemo(() => {
96
+ if (!library) return false;
97
+ if (titleDraft.trim() !== (library.title ?? "").trim()) return true;
98
+ if (descriptionDraft.trim() !== (library.description ?? "").trim())
99
+ return true;
100
+ if (styleDescriptionDraft !== (library.styleBrief?.description ?? ""))
101
+ return true;
102
+ if (
103
+ customInstructionsDraft.trim() !==
104
+ (getLibraryCustomInstructions(library) ?? "")
105
+ )
106
+ return true;
107
+ if (
108
+ parsePaletteDraft(paletteDraft).join(", ") !==
109
+ paletteDraftFromColors(library.styleBrief?.palette)
110
+ )
111
+ return true;
112
+ return false;
113
+ }, [
114
+ library,
115
+ titleDraft,
116
+ descriptionDraft,
117
+ styleDescriptionDraft,
118
+ customInstructionsDraft,
119
+ paletteDraft,
120
+ ]);
121
+
122
+ useEffect(() => {
123
+ if (!library) return;
124
+ if (initializedLibraryId === library.id && isDirty) return;
125
+ setTitleDraft(library.title ?? "");
126
+ setDescriptionDraft(library.description ?? "");
127
+ setStyleDescriptionDraft(library.styleBrief?.description ?? "");
128
+ setCustomInstructionsDraft(getLibraryCustomInstructions(library) ?? "");
129
+ setPaletteDraft(paletteDraftFromColors(library.styleBrief?.palette));
130
+ if (initializedLibraryId !== library.id) {
131
+ const isNewLibrary =
132
+ !library.description &&
133
+ !getLibraryCustomInstructions(library) &&
134
+ !library.styleBrief?.description &&
135
+ !(library.styleBrief?.palette ?? []).length;
136
+ setDetailsOpen(isNewLibrary);
137
+ setInitializedLibraryId(library.id);
138
+ }
139
+ }, [library, initializedLibraryId, isDirty]);
140
+
141
+ const isTitleValid = titleDraft.trim().length > 0;
142
+
143
+ function saveAll() {
144
+ if (!library || !isDirty || !isTitleValid) return;
145
+ const trimmedTitle = titleDraft.trim();
146
+ const palette = parsePaletteDraft(paletteDraft);
147
+ updateLibrary.mutate(
148
+ {
149
+ id: library.id,
150
+ title: trimmedTitle,
151
+ description: descriptionDraft.trim() || null,
152
+ customInstructions: customInstructionsDraft.trim(),
153
+ styleBrief: {
154
+ ...library.styleBrief,
155
+ description: styleDescriptionDraft,
156
+ palette,
157
+ },
158
+ },
159
+ {
160
+ onSuccess: () => {
161
+ setPaletteDraft(palette.join(", "));
162
+ toast.success(t("brandKits.updated"));
163
+ },
164
+ onError: (error: Error) =>
165
+ toast.error(error.message || t("brandKits.updateFailed")),
166
+ },
167
+ );
168
+ }
169
+
170
+ const navigationBlocker = useBlocker(
171
+ useCallback(
172
+ ({ currentLocation, nextLocation }) =>
173
+ isDirty && currentLocation.pathname !== nextLocation.pathname,
174
+ [isDirty],
175
+ ),
176
+ );
177
+
178
+ useBeforeUnload(
179
+ useCallback(
180
+ (event: BeforeUnloadEvent) => {
181
+ if (!isDirty) return;
182
+ event.preventDefault();
183
+ event.returnValue = "";
184
+ },
185
+ [isDirty],
186
+ ),
187
+ );
188
+
189
+ function handleBack() {
190
+ navigate(`/library/${libraryId}`);
191
+ }
192
+
193
+ function keepEditing() {
194
+ if (navigationBlocker.state === "blocked") navigationBlocker.reset();
195
+ }
196
+
197
+ function discardAndLeave() {
198
+ if (navigationBlocker.state === "blocked") navigationBlocker.proceed();
199
+ }
200
+
201
+ function analyzeBrand() {
202
+ if (!library) return;
203
+ const referenceCount = assets.filter(
204
+ (asset) => asset.status === "reference",
205
+ ).length;
206
+ sendToAgentChat({
207
+ message: [
208
+ "Analyze this Assets library brand.",
209
+ `Call analyze-collection-style with libraryId: ${library.id}.`,
210
+ "Update the reusable style brief with palette and visual traits, then summarize what changed.",
211
+ ].join("\n"),
212
+ context: [
213
+ "## Assets library context",
214
+ `Library: ${library.title} (${library.id})`,
215
+ `Description: ${library.description || ""}`,
216
+ `Reference assets: ${referenceCount}`,
217
+ `Current style brief: ${JSON.stringify(library.styleBrief ?? {})}`,
218
+ getLibraryCustomInstructions(library)
219
+ ? `Custom instructions: ${getLibraryCustomInstructions(library)}`
220
+ : "Custom instructions: none",
221
+ ].join("\n"),
222
+ submit: true,
223
+ newTab: true,
224
+ });
225
+ }
226
+
227
+ useSetPageTitle(
228
+ <div className="flex min-w-0 items-center gap-2">
229
+ <Button
230
+ variant="ghost"
231
+ size="icon"
232
+ className="-ms-2 h-7 w-7 shrink-0"
233
+ onClick={handleBack}
234
+ aria-label={t("brandKitDetail.backToLibrary")}
235
+ >
236
+ <IconArrowLeft className="h-4 w-4" />
237
+ </Button>
238
+ <h1 className="truncate text-lg font-semibold tracking-tight">
239
+ {t("brandKitDetail.settingsTitle")}
240
+ </h1>
241
+ {library ? <Badge variant="outline">{library.title}</Badge> : null}
242
+ </div>,
243
+ );
244
+
245
+ useSetHeaderActions(
246
+ library ? (
247
+ <Button
248
+ size="sm"
249
+ onClick={saveAll}
250
+ disabled={!isDirty || !isTitleValid || updateLibrary.isPending}
251
+ >
252
+ {updateLibrary.isPending
253
+ ? t("brandKitDetail.saving")
254
+ : t("brandKitDetail.save")}
255
+ </Button>
256
+ ) : null,
257
+ );
258
+
259
+ if (!library) {
260
+ return (
261
+ <div className="p-6 text-sm text-muted-foreground">
262
+ {t("library.loadingBrandKit")}
263
+ </div>
264
+ );
265
+ }
266
+
267
+ return (
268
+ <div className="mx-auto flex w-full max-w-5xl flex-col gap-6 px-6 py-6">
269
+ <div className="flex flex-col gap-4">
270
+ <div className="space-y-4 rounded-lg border border-border p-4">
271
+ <Label htmlFor="brand-kit-title">{t("brandKitDetail.name")}</Label>
272
+ <Input
273
+ id="brand-kit-title"
274
+ value={titleDraft}
275
+ onChange={(event) => setTitleDraft(event.target.value)}
276
+ placeholder={t("brandKits.namePlaceholder")}
277
+ />
278
+ <Label htmlFor="brand-kit-description">
279
+ {t("assetDetail.description")}
280
+ </Label>
281
+ <Textarea
282
+ id="brand-kit-description"
283
+ value={descriptionDraft}
284
+ onChange={(event) => setDescriptionDraft(event.target.value)}
285
+ placeholder={t("brandKits.editDescriptionPlaceholder")}
286
+ />
287
+ <div>
288
+ <h3 className="text-sm font-semibold">
289
+ {t("brandKitDetail.agentUsage")}
290
+ </h3>
291
+ <p className="mt-2 text-sm text-muted-foreground">
292
+ {t("brandKitDetail.agentUsageDescription")}
293
+ </p>
294
+ <code className="mt-3 block rounded-md bg-muted p-3 text-xs">
295
+ {library.id}
296
+ </code>
297
+ </div>
298
+ </div>
299
+
300
+ <div className="rounded-lg border border-border p-4">
301
+ <button
302
+ type="button"
303
+ className="flex w-full items-center justify-between gap-2 text-left"
304
+ onClick={() => setDetailsOpen((open) => !open)}
305
+ aria-expanded={detailsOpen}
306
+ >
307
+ <div>
308
+ <h3 className="text-sm font-semibold">
309
+ {t("brandKitDetail.setupGuide")}
310
+ </h3>
311
+ <p className="mt-1 text-sm text-muted-foreground">
312
+ {t("brandKitDetail.setupGuideDescription")}
313
+ </p>
314
+ </div>
315
+ {detailsOpen ? (
316
+ <IconChevronDown className="h-4 w-4 shrink-0 text-muted-foreground" />
317
+ ) : (
318
+ <IconChevronRight className="h-4 w-4 shrink-0 text-muted-foreground" />
319
+ )}
320
+ </button>
321
+ {detailsOpen ? (
322
+ <ul className="mt-4 space-y-3">
323
+ <li className="flex gap-3">
324
+ <IconPhoto className="mt-0.5 h-4 w-4 shrink-0 text-muted-foreground" />
325
+ <div>
326
+ <div className="text-sm font-medium">
327
+ {t("brandKitDetail.setupGuideReferences")}
328
+ </div>
329
+ <p className="text-sm text-muted-foreground">
330
+ {t("brandKitDetail.setupGuideReferencesHint")}
331
+ </p>
332
+ </div>
333
+ </li>
334
+ <li className="flex gap-3">
335
+ <IconTextCaption className="mt-0.5 h-4 w-4 shrink-0 text-muted-foreground" />
336
+ <div>
337
+ <div className="text-sm font-medium">
338
+ {t("brandKitDetail.setupGuideStyleDescription")}
339
+ </div>
340
+ <p className="text-sm text-muted-foreground">
341
+ {t("brandKitDetail.setupGuideStyleDescriptionHint")}
342
+ </p>
343
+ </div>
344
+ </li>
345
+ <li className="flex gap-3">
346
+ <IconListCheck className="mt-0.5 h-4 w-4 shrink-0 text-muted-foreground" />
347
+ <div>
348
+ <div className="text-sm font-medium">
349
+ {t("brandKitDetail.setupGuideInstructions")}
350
+ </div>
351
+ <p className="text-sm text-muted-foreground">
352
+ {t("brandKitDetail.setupGuideInstructionsHint")}
353
+ </p>
354
+ </div>
355
+ </li>
356
+ <li className="flex gap-3">
357
+ <IconBulb className="mt-0.5 h-4 w-4 shrink-0 text-muted-foreground" />
358
+ <div>
359
+ <div className="text-sm font-medium">
360
+ {t("brandKitDetail.setupGuidePresets")}
361
+ </div>
362
+ <p className="text-sm text-muted-foreground">
363
+ {t("brandKitDetail.setupGuidePresetsHint")}
364
+ </p>
365
+ </div>
366
+ </li>
367
+ </ul>
368
+ ) : null}
369
+ </div>
370
+ </div>
371
+
372
+ <div className="space-y-4 rounded-lg border border-border p-4">
373
+ <Label>{t("brandKitDetail.styleDescription")}</Label>
374
+ <Textarea
375
+ value={styleDescriptionDraft}
376
+ onChange={(event) => setStyleDescriptionDraft(event.target.value)}
377
+ className="min-h-40"
378
+ />
379
+ <Label>{t("brandKitDetail.customInstructions")}</Label>
380
+ <Textarea
381
+ value={customInstructionsDraft}
382
+ onChange={(event) => setCustomInstructionsDraft(event.target.value)}
383
+ placeholder={t("brandKitDetail.customInstructionsPlaceholder")}
384
+ className="min-h-28"
385
+ />
386
+ <div className="flex items-center justify-between gap-3">
387
+ <div>
388
+ <div className="text-sm font-medium">
389
+ {t("brandKitDetail.palette")}
390
+ </div>
391
+ <div className="mt-2 flex flex-wrap gap-2">
392
+ {(library.styleBrief?.palette ?? []).map((color: string) => (
393
+ <span
394
+ key={color}
395
+ className="h-7 w-7 rounded-md border border-border"
396
+ style={{ backgroundColor: color }}
397
+ title={color}
398
+ />
399
+ ))}
400
+ </div>
401
+ <Input
402
+ value={paletteDraft}
403
+ onChange={(event) => setPaletteDraft(event.target.value)}
404
+ placeholder={"#111827, #f8fafc, #2563eb"}
405
+ className="mt-3 h-9 max-w-md text-xs"
406
+ />
407
+ </div>
408
+ <Button variant="outline" onClick={analyzeBrand}>
409
+ {library.settings?.brandAnalysis?.analyzedAt
410
+ ? t("brandKitDetail.refreshBrand")
411
+ : t("brandKitDetail.analyzeBrand")}
412
+ </Button>
413
+ </div>
414
+ </div>
415
+
416
+ <GenerationPresetsPanel
417
+ libraryId={libraryId}
418
+ presets={generationPresets}
419
+ />
420
+
421
+ <Dialog
422
+ open={navigationBlocker.state === "blocked"}
423
+ onOpenChange={(open) => {
424
+ if (!open) keepEditing();
425
+ }}
426
+ >
427
+ <DialogContent>
428
+ <DialogHeader>
429
+ <DialogTitle>{t("brandKitDetail.unsavedChangesTitle")}</DialogTitle>
430
+ <DialogDescription>
431
+ {t("brandKitDetail.unsavedChangesDescription")}
432
+ </DialogDescription>
433
+ </DialogHeader>
434
+ <DialogFooter>
435
+ <Button variant="outline" onClick={keepEditing}>
436
+ {t("brandKitDetail.keepEditing")}
437
+ </Button>
438
+ <Button variant="destructive" onClick={discardAndLeave}>
439
+ {t("brandKitDetail.discardChanges")}
440
+ </Button>
441
+ </DialogFooter>
442
+ </DialogContent>
443
+ </Dialog>
444
+ </div>
445
+ );
446
+ }
@@ -16,6 +16,8 @@ import {
16
16
  writeClientAppState,
17
17
  } from "@agent-native/core/client";
18
18
  import {
19
+ AGENT_NATIVE_EMBED_MESSAGE_TYPES,
20
+ createAgentNativeEmbedEnvelope,
19
21
  createEmbeddedAppBridge,
20
22
  type EmbeddedAppBridge,
21
23
  } from "@agent-native/core/embedding";
@@ -244,6 +246,31 @@ function isEmbeddedWindow() {
244
246
  }
245
247
  }
246
248
 
249
+ interface StandalonePickerHandoff {
250
+ handoffId: string;
251
+ returnOrigin: string;
252
+ }
253
+
254
+ function standalonePickerHandoff(): StandalonePickerHandoff | null {
255
+ if (typeof window === "undefined") return null;
256
+ const params = new URLSearchParams(window.location.search);
257
+ const handoffId = params.get("__an_asset_picker_handoff")?.trim();
258
+ const rawReturnOrigin = params.get("__an_asset_picker_return_origin")?.trim();
259
+ if (!handoffId || handoffId.length > 128 || !rawReturnOrigin) return null;
260
+ try {
261
+ const parsed = new URL(rawReturnOrigin);
262
+ if (
263
+ (parsed.protocol !== "http:" && parsed.protocol !== "https:") ||
264
+ parsed.origin !== rawReturnOrigin
265
+ ) {
266
+ return null;
267
+ }
268
+ return { handoffId, returnOrigin: parsed.origin };
269
+ } catch {
270
+ return null;
271
+ }
272
+ }
273
+
247
274
  function normalizeCount(value: unknown): number {
248
275
  if (value === null || value === undefined || value === "") return 3;
249
276
  const count = Number(value);
@@ -2206,6 +2233,10 @@ export function AssetPickerSurface() {
2206
2233
  isEmbedAuthActive(),
2207
2234
  [searchParams],
2208
2235
  );
2236
+ const standaloneHandoff = useMemo(
2237
+ () => (embedded ? null : standalonePickerHandoff()),
2238
+ [embedded],
2239
+ );
2209
2240
  const pickerVariantScopeId = useMemo(
2210
2241
  () =>
2211
2242
  typeof window === "undefined" ? null : `picker:${getBrowserTabId()}`,
@@ -2552,6 +2583,35 @@ export function AssetPickerSurface() {
2552
2583
  [],
2553
2584
  );
2554
2585
 
2586
+ const postStandaloneSelectionMessage = useCallback(
2587
+ (payload: ReturnType<typeof assetPayload>) => {
2588
+ if (
2589
+ !standaloneHandoff ||
2590
+ typeof window === "undefined" ||
2591
+ !window.opener ||
2592
+ window.opener.closed
2593
+ ) {
2594
+ return false;
2595
+ }
2596
+ try {
2597
+ window.opener.postMessage(
2598
+ createAgentNativeEmbedEnvelope(
2599
+ AGENT_NATIVE_EMBED_MESSAGE_TYPES.MESSAGE,
2600
+ {
2601
+ name: "chooseAsset",
2602
+ payload: { ...payload, handoffId: standaloneHandoff.handoffId },
2603
+ },
2604
+ ),
2605
+ standaloneHandoff.returnOrigin,
2606
+ );
2607
+ return true;
2608
+ } catch {
2609
+ return false;
2610
+ }
2611
+ },
2612
+ [standaloneHandoff],
2613
+ );
2614
+
2555
2615
  const chooseAsset = (asset: Asset) => {
2556
2616
  const payload = assetPayload(asset, mediaType);
2557
2617
  if (embedded) {
@@ -2574,6 +2634,15 @@ export function AssetPickerSurface() {
2574
2634
  });
2575
2635
  return;
2576
2636
  }
2637
+ if (postStandaloneSelectionMessage(payload)) {
2638
+ toast.success(
2639
+ t("assetPicker.selectedAsset", {
2640
+ title: selectedAssetLabel(payload),
2641
+ }),
2642
+ );
2643
+ window.setTimeout(() => window.close(), 0);
2644
+ return;
2645
+ }
2577
2646
  setStandaloneSelection(payload);
2578
2647
  setStandaloneCopyOk(false);
2579
2648
  void copyStandaloneSelection(payload);
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-15
4
+ ---
5
+
6
+ Fixed top-level image picker selections returning to the composer
@@ -13,10 +13,11 @@ import { writeAppState } from "@agent-native/core/application-state";
13
13
  import { deleteAppSecret, readAppSecret } from "@agent-native/core/secrets";
14
14
  import { getRequestUserEmail } from "@agent-native/core/server/request-context";
15
15
  import { assertAccess } from "@agent-native/core/sharing";
16
- import { eq } from "drizzle-orm";
16
+ import { and, eq, inArray, isNull, or } from "drizzle-orm";
17
17
  import { z } from "zod";
18
18
 
19
19
  import { getDb, schema } from "../server/db/index.js";
20
+ import { lockCalendarAccount } from "../server/lib/calendar-event-meetings.js";
20
21
  import { revokeToken } from "../server/lib/google-calendar-client.js";
21
22
 
22
23
  export default defineAction({
@@ -90,15 +91,62 @@ export default defineAction({
90
91
  }).catch(() => {});
91
92
  }
92
93
 
93
- // Drop the synced events for this account so the meetings tab clears.
94
- await db
95
- .delete(schema.calendarEvents)
96
- .where(eq(schema.calendarEvents.calendarAccountId, args.id));
94
+ await db.transaction(async (tx) => {
95
+ // Materialization takes this same account-row write lock before it
96
+ // snapshots/claims an event and inserts a meeting. Taking it before
97
+ // this cleanup snapshot prevents a new unrecorded meeting from being
98
+ // inserted after the rows below have been inspected.
99
+ if (!(await lockCalendarAccount(tx, args.id, account.ownerEmail))) {
100
+ throw new Error(`Calendar account not found: ${args.id}`);
101
+ }
97
102
 
98
- // Drop the account row itself.
99
- await db
100
- .delete(schema.calendarAccounts)
101
- .where(eq(schema.calendarAccounts.id, args.id));
103
+ // Preserve recorded meetings, but hide unrecorded calendar placeholders
104
+ // tied to this account. Without this cleanup, those materialized rows
105
+ // stay visible after the account and its event cache are removed.
106
+ const syncedEvents = await tx
107
+ .select({
108
+ id: schema.calendarEvents.id,
109
+ meetingId: schema.calendarEvents.meetingId,
110
+ })
111
+ .from(schema.calendarEvents)
112
+ .where(eq(schema.calendarEvents.calendarAccountId, args.id));
113
+ const syncedCalendarEventIds = syncedEvents.map((event) => event.id);
114
+ const syncedMeetingIds = syncedEvents
115
+ .map((event) => event.meetingId)
116
+ .filter((meetingId): meetingId is string => Boolean(meetingId));
117
+ if (syncedCalendarEventIds.length > 0 || syncedMeetingIds.length > 0) {
118
+ await tx
119
+ .update(schema.meetings)
120
+ .set({ trashedAt: new Date().toISOString() })
121
+ .where(
122
+ and(
123
+ or(
124
+ syncedMeetingIds.length > 0
125
+ ? inArray(schema.meetings.id, syncedMeetingIds)
126
+ : undefined,
127
+ syncedCalendarEventIds.length > 0
128
+ ? inArray(
129
+ schema.meetings.calendarEventId,
130
+ syncedCalendarEventIds,
131
+ )
132
+ : undefined,
133
+ )!,
134
+ isNull(schema.meetings.recordingId),
135
+ isNull(schema.meetings.trashedAt),
136
+ ),
137
+ );
138
+ }
139
+
140
+ // Drop the synced events for this account so the meetings tab clears.
141
+ await tx
142
+ .delete(schema.calendarEvents)
143
+ .where(eq(schema.calendarEvents.calendarAccountId, args.id));
144
+
145
+ // Drop the account row itself.
146
+ await tx
147
+ .delete(schema.calendarAccounts)
148
+ .where(eq(schema.calendarAccounts.id, args.id));
149
+ });
102
150
 
103
151
  await writeAppState("refresh-signal", { ts: Date.now() });
104
152
  return { id: args.id, disconnected: true };